From 267d1ab2ba5adfeeb18820c4fd839037a13441dd Mon Sep 17 00:00:00 2001 From: robert-hh Date: Tue, 14 Mar 2023 12:41:42 +0100 Subject: [PATCH 01/10] samd/mpconfigport: Drop support for SoftSPI max speed. Saves ~140 bytes and is not really needed, since for higher baud rates hard SPI is available. Signed-off-by: robert-hh --- ports/samd/mpconfigport.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index bc1ad3d9889eb..3b89ee082bfd4 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -99,8 +99,6 @@ #define MICROPY_PY_MACHINE_SOFTI2C (1) #define MICROPY_PY_MACHINE_SPI (1) #define MICROPY_PY_MACHINE_SOFTSPI (1) -#define MICROPY_HW_SOFTSPI_MIN_DELAY (1) -#define MICROPY_HW_SOFTSPI_MAX_BAUDRATE (1000000) #define MICROPY_PY_MACHINE_TIMER (1) #define MICROPY_SOFT_TIMER_TICKS_MS systick_ms #define MICROPY_PY_OS_DUPTERM (3) From 457d9ee68a1e603648eb195c50175c7862be7a7e Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 18 Mar 2023 22:12:51 +0100 Subject: [PATCH 02/10] samd/boards/MINISAM_M4: Update pins.csv for the Mini SAM M4 board. Signed-off-by: robert-hh --- ports/samd/boards/MINISAM_M4/pins.csv | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/ports/samd/boards/MINISAM_M4/pins.csv b/ports/samd/boards/MINISAM_M4/pins.csv index f676c290a05f6..793e523fcd96c 100644 --- a/ports/samd/boards/MINISAM_M4/pins.csv +++ b/ports/samd/boards/MINISAM_M4/pins.csv @@ -3,18 +3,19 @@ # If the pin name is omitted, the pin number is added as name. # Empty lines and lines not starting with PIN_ are ignored -PIN_PA02,A0_D9 -PIN_PB08,A1_D10 -PIN_PB09,A2_D11 -PIN_PA04,A3_D12 -PIN_PA05,A4_D13 +PIN_PA02,A0 +PIN_PB08,A1 +PIN_PB09,A2 +PIN_PA04,A3 +PIN_PA05,A4 PIN_PA06,A5 -PIN_PA16,D0 -PIN_PA17,D1 -PIN_PA07,A6_D2 +PIN_PA07,A6 +PIN_PA16,RX +PIN_PA17,TX PIN_PA19,D3 PIN_PA20,D4 PIN_PA21,D5 +PIN_PA15,LED PIN_PA00,BUTTON PIN_PA03,AREF PIN_PA12,SDA @@ -25,8 +26,6 @@ PIN_PA01,SCK PIN_PB03,DOTSTAR_DATA PIN_PB02,DOTSTAR_CLK -PIN_PA15,LED - PIN_PA24,USB_DM PIN_PA25,USB_DP PIN_PA26,USB_SOF From 315eb949da3bb3fe476050e164f03b613ca64afa Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 27 Jan 2023 16:02:05 +0100 Subject: [PATCH 03/10] samd: Rearrange the MCU-specific loader files. Such that they are easier to adapt. The maximum code size is set by: MICROPY_HW_CODESIZE=xxxK in mpconfigmcu.mk for the MCU family as default or in mpconfigboard.mk for a specific board. Setting the maximum code size allows the loader to error out if the code gets larger than the space dedicated for it. Signed-off-by: robert-hh --- ports/samd/Makefile | 3 +++ ports/samd/boards/samd21x18a.ld | 14 +++++++++++--- ports/samd/boards/samd51x19a.ld | 14 +++++++++++--- ports/samd/boards/samd51x20a.ld | 14 +++++++++++--- ports/samd/mcu/samd21/mpconfigmcu.mk | 2 ++ ports/samd/mcu/samd51/mpconfigmcu.mk | 2 ++ 6 files changed, 40 insertions(+), 9 deletions(-) diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 290453f50b939..6f7c8fbd85ad3 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -65,7 +65,10 @@ CFLAGS += $(INC) -Wall -Werror -std=c99 -nostdlib -mthumb $(CFLAGS_MCU) -fsingle CFLAGS += -DMCU_$(MCU_SERIES) -D__$(CMSIS_MCU)__ CFLAGS += $(CFLAGS_EXTRA) +CFLAGS += -DMICROPY_HW_CODESIZE=$(MICROPY_HW_CODESIZE) + LDFLAGS += -nostdlib $(addprefix -T,$(LD_FILES)) -Map=$@.map --cref +LDFLAGS += --defsym=_codesize=$(MICROPY_HW_CODESIZE) LIBS += $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) diff --git a/ports/samd/boards/samd21x18a.ld b/ports/samd/boards/samd21x18a.ld index 81a84a15d7d75..3ab051569fb18 100644 --- a/ports/samd/boards/samd21x18a.ld +++ b/ports/samd/boards/samd21x18a.ld @@ -2,10 +2,18 @@ GNU linker script for SAMD21 */ +/* +_codesize is defined in mpconfigmcu.mk or mpconfigboard.mk as +MICROPY_HW_CODESIZE and is set in Makefile +*/ + +_flashsize = 256K; /* The physical flash size */ +_bootloader = 8K; /* Must match the ORIGIN value of FLASH */ + /* Specify the memory areas */ MEMORY { - FLASH (rx) : ORIGIN = 0x00002000, LENGTH = 256K - 8K + FLASH (rx) : ORIGIN = 0x00002000, LENGTH = _codesize RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K } @@ -13,8 +21,8 @@ MEMORY _estack = ORIGIN(RAM) + LENGTH(RAM) - 8; _sstack = _estack - 8K; -_oflash_fs = ORIGIN(FLASH) + 192K - 8K; -_sflash_fs = LENGTH(FLASH) - 192K + 8K - 1; +_oflash_fs = ORIGIN(FLASH) + _codesize; +_sflash_fs = _flashsize - _codesize - _bootloader; _sheap = _ebss; _eheap = _sstack; diff --git a/ports/samd/boards/samd51x19a.ld b/ports/samd/boards/samd51x19a.ld index cd03320ba43d7..30bc8e33281fb 100644 --- a/ports/samd/boards/samd51x19a.ld +++ b/ports/samd/boards/samd51x19a.ld @@ -2,10 +2,18 @@ GNU linker script for SAMD51 */ +/* +_codesize is defined in mpconfigmcu.mk or mpconfigboard.mk as +MICROPY_HW_CODESIZE and is set in Makefile +*/ + +_flashsize = 512K; /* The physical flash size */ +_bootloader = 16K; /* Must match the ORIGIN value of FLASH */ + /* Specify the memory areas */ MEMORY { - FLASH (rx) : ORIGIN = 0x00004000, LENGTH = 512K - 16K + FLASH (rx) : ORIGIN = 0x00004000, LENGTH = _codesize RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K } @@ -13,8 +21,8 @@ MEMORY _estack = ORIGIN(RAM) + LENGTH(RAM) - 8; _sstack = _estack - 16K; -_oflash_fs = ORIGIN(FLASH) + 384K - 16K; -_sflash_fs = LENGTH(FLASH) - 384K + 16K - 1; +_oflash_fs = ORIGIN(FLASH) + _codesize; +_sflash_fs = _flashsize - _codesize - _bootloader; _sheap = _ebss; _eheap = _sstack; diff --git a/ports/samd/boards/samd51x20a.ld b/ports/samd/boards/samd51x20a.ld index f0d5e5c6aeb60..472ab316c6fde 100644 --- a/ports/samd/boards/samd51x20a.ld +++ b/ports/samd/boards/samd51x20a.ld @@ -2,10 +2,18 @@ GNU linker script for SAMD51x20 */ +/* +_codesize is defined in mpconfigmcu.mk or mpconfigboard.mk as +MICROPY_HW_CODESIZE and is set in Makefile +*/ + +_flashsize = 1024K; /* The physical flash size */ +_bootloader = 16K; /* Must match the ORIGIN value of FLASH */ + /* Specify the memory areas */ MEMORY { - FLASH (rx) : ORIGIN = 0x00004000, LENGTH = 1024K - 16K + FLASH (rx) : ORIGIN = 0x00004000, LENGTH = _codesize RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 256K } @@ -13,8 +21,8 @@ MEMORY _estack = ORIGIN(RAM) + LENGTH(RAM) - 8; _sstack = _estack - 16K; -_oflash_fs = ORIGIN(FLASH) + 384K - 16K; -_sflash_fs = LENGTH(FLASH) - 384K + 16K - 1; +_oflash_fs = ORIGIN(FLASH) + _codesize; +_sflash_fs = _flashsize - _codesize - _bootloader; _sheap = _ebss; _eheap = _sstack; diff --git a/ports/samd/mcu/samd21/mpconfigmcu.mk b/ports/samd/mcu/samd21/mpconfigmcu.mk index ddd3e8b410113..2e16d12a2dc21 100644 --- a/ports/samd/mcu/samd21/mpconfigmcu.mk +++ b/ports/samd/mcu/samd21/mpconfigmcu.mk @@ -2,6 +2,8 @@ CFLAGS_MCU += -mtune=cortex-m0plus -mcpu=cortex-m0plus -msoft-float MPY_CROSS_MCU_ARCH = armv6m +MICROPY_HW_CODESIZE ?= 184K + SRC_S += shared/runtime/gchelper_thumb1.s LIBM_SRC_C += $(addprefix lib/libm/,\ diff --git a/ports/samd/mcu/samd51/mpconfigmcu.mk b/ports/samd/mcu/samd51/mpconfigmcu.mk index 8596f59821114..433404fd11ac5 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.mk +++ b/ports/samd/mcu/samd51/mpconfigmcu.mk @@ -2,6 +2,8 @@ CFLAGS_MCU += -mtune=cortex-m4 -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=har MPY_CROSS_MCU_ARCH = armv7m +MICROPY_HW_CODESIZE ?= 368K + MICROPY_VFS_LFS2 ?= 1 MICROPY_VFS_FAT ?= 1 FROZEN_MANIFEST ?= mcu/$(MCU_SERIES_LOWER)/manifest.py From 05e684dc0717b27ba52eeac7c480ebb6aa032fac Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 30 Mar 2023 16:07:35 +0200 Subject: [PATCH 04/10] samd/mcu/samd51: Enable MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF. Signed-off-by: robert-hh --- ports/samd/mcu/samd51/mpconfigmcu.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ports/samd/mcu/samd51/mpconfigmcu.h b/ports/samd/mcu/samd51/mpconfigmcu.h index 5ac431b29707b..0598c353d6c0e 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.h +++ b/ports/samd/mcu/samd51/mpconfigmcu.h @@ -7,6 +7,9 @@ #define MICROPY_EMIT_THUMB (1) #define MICROPY_EMIT_INLINE_THUMB (1) +// Python internal features +#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) + #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) #ifndef MICROPY_PY_BUILTINS_COMPLEX From b7180d53f091c645a39377ddc17ee9d0bae2767f Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 6 Apr 2023 16:21:58 +0200 Subject: [PATCH 05/10] samd/boards: Add default deploy instructions. Signed-off-by: robert-hh --- ports/samd/boards/deploy.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ports/samd/boards/deploy.md b/ports/samd/boards/deploy.md index e69de29bb2d1d..fac5c994ab702 100644 --- a/ports/samd/boards/deploy.md +++ b/ports/samd/boards/deploy.md @@ -0,0 +1,10 @@ +For deploying the MicroPython firmware to the SAMD module, follow +the procedure: + +- Push the reset button twice or call machine.bootloader(). A drive + icon should appear representing a virtual drive. + +- Copy the .uf2 file with the required firmware to that drive. + +As soon as the drive disappears, the firmware is loaded and started. + From 7a847bab1e448c428ecd5d1ad1b7c66b70009587 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 7 Apr 2023 17:34:15 +0200 Subject: [PATCH 06/10] samd/main: Fix sercom deinit ordering in soft-reset. If sockets were open when calling soft reset, gc_sweep_all() would try to close them. In case of e.g. the NINA WiFi handler, connected through SPI, spi_transfer() would be called for command exchange with the NINA module. But at that time SerCom was already disabled. Moving sercom_deinit_all() behind gc_sweep_all() solves this issue. Signed-off-by: robert-hh --- ports/samd/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/samd/main.c b/ports/samd/main.c index bc0e45ee64db2..1e30df13d40d9 100644 --- a/ports/samd/main.c +++ b/ports/samd/main.c @@ -84,9 +84,9 @@ void samd_main(void) { adc_deinit_all(); pin_irq_deinit_all(); pwm_deinit_all(); - sercom_deinit_all(); soft_timer_deinit(); gc_sweep_all(); + sercom_deinit_all(); mp_deinit(); } } From b2df094bf8051758b10f2f0222e09e79ed97427e Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 9 Apr 2023 14:14:16 +0200 Subject: [PATCH 07/10] samd/modmachine: Add machine.deepsleep as alias of machine.lightsleep. Just for coverage. Signed-off-by: robert-hh --- ports/samd/modmachine.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index ec3e99f163a55..a2ef34b99d3d6 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -256,6 +256,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) }, { MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) }, { MP_ROM_QSTR(MP_QSTR_lightsleep), MP_ROM_PTR(&machine_lightsleep_obj) }, + { MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_lightsleep_obj) }, { MP_ROM_QSTR(MP_QSTR_bitstream), MP_ROM_PTR(&machine_bitstream_obj) }, #if MICROPY_PY_MACHINE_DHT_READINTO From 47fa723586dc4ae81df02f5a0a10b2b018045ab0 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 11 Mar 2023 08:03:18 +0100 Subject: [PATCH 08/10] samd/modmachine: Make some machine classes configurable by #defines. These include ADC, DAC, I2C, SoftI2C, SPI, SoftI2C, PWM, UART, pulse. This is useful for devices like the Adafruit Trinket series which have almost no accessible GPIO pins. Signed-off-by: robert-hh --- ports/samd/machine_adc.c | 16 +++++++--------- ports/samd/machine_dac.c | 7 ++++++- ports/samd/machine_i2c.c | 5 +++++ ports/samd/machine_pwm.c | 7 ++++++- ports/samd/machine_spi.c | 17 ++++++----------- ports/samd/machine_uart.c | 33 ++++++++++++++++++++++++++------- ports/samd/machine_wdt.c | 9 ++++++++- ports/samd/main.c | 6 ++++++ ports/samd/modmachine.c | 18 ++++++++++++++++++ ports/samd/modmachine.h | 12 ++++++++++++ ports/samd/mpconfigport.h | 25 +++++++++++++++++++++++-- ports/samd/pin_af.c | 8 ++++++++ 12 files changed, 131 insertions(+), 32 deletions(-) diff --git a/ports/samd/machine_adc.c b/ports/samd/machine_adc.c index 8f47fc6d15182..1d848e32bc506 100644 --- a/ports/samd/machine_adc.c +++ b/ports/samd/machine_adc.c @@ -25,9 +25,12 @@ * THE SOFTWARE. */ +#include "py/runtime.h" + +#if MICROPY_PY_MACHINE_ADC + #include #include "py/obj.h" -#include "py/runtime.h" #include "py/mphal.h" #include "sam.h" @@ -82,14 +85,7 @@ static uint8_t resolution[] = { ADC_CTRLB_RESSEL_8BIT_Val, ADC_CTRLB_RESSEL_10BIT_Val, ADC_CTRLB_RESSEL_12BIT_Val }; -// Calculate the floor value of log2(n) -mp_int_t log2i(mp_int_t num) { - mp_int_t res = 0; - for (; num > 1; num >>= 1) { - res += 1; - } - return res; -} +extern mp_int_t log2i(mp_int_t num); STATIC void adc_obj_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind) { (void)kind; @@ -274,3 +270,5 @@ static void adc_init(machine_adc_obj_t *self) { // Set the port as given in self->id as ADC mp_hal_set_pin_mux(self->id, ALT_FCT_ADC); } + +#endif diff --git a/ports/samd/machine_dac.c b/ports/samd/machine_dac.c index a1da9285e5fbe..195c06e4f4a83 100644 --- a/ports/samd/machine_dac.c +++ b/ports/samd/machine_dac.c @@ -25,9 +25,12 @@ * THE SOFTWARE. */ +#include "py/runtime.h" + +#if MICROPY_PY_MACHINE_DAC + #include #include "py/obj.h" -#include "py/runtime.h" #include "py/mphal.h" #include "sam.h" @@ -183,3 +186,5 @@ MP_DEFINE_CONST_OBJ_TYPE( print, dac_print, locals_dict, &dac_locals_dict ); + +#endif diff --git a/ports/samd/machine_i2c.c b/ports/samd/machine_i2c.c index 330fa433d96e6..f3364950bdb71 100644 --- a/ports/samd/machine_i2c.c +++ b/ports/samd/machine_i2c.c @@ -26,6 +26,9 @@ */ #include "py/runtime.h" + +#if MICROPY_PY_MACHINE_I2C + #include "py/mphal.h" #include "py/mperrno.h" #include "extmod/machine_i2c.h" @@ -274,3 +277,5 @@ MP_DEFINE_CONST_OBJ_TYPE( protocol, &machine_i2c_p, locals_dict, &mp_machine_i2c_locals_dict ); + +#endif diff --git a/ports/samd/machine_pwm.c b/ports/samd/machine_pwm.c index d01ce2ff1ad5b..1b5f6c3ed8dd1 100644 --- a/ports/samd/machine_pwm.c +++ b/ports/samd/machine_pwm.c @@ -25,8 +25,11 @@ * THE SOFTWARE. */ -#include #include "py/runtime.h" + +#if MICROPY_PY_MACHINE_PWM + +#include #include "py/mphal.h" #include "modmachine.h" #include "clock_config.h" @@ -393,3 +396,5 @@ STATIC void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty_ns duty_type_flags[self->device] &= ~(1 << self->channel); mp_machine_pwm_start(self); } + +#endif diff --git a/ports/samd/machine_spi.c b/ports/samd/machine_spi.c index bbd7031e940eb..99eb4e17f6517 100644 --- a/ports/samd/machine_spi.c +++ b/ports/samd/machine_spi.c @@ -24,7 +24,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + #include "py/runtime.h" + +#if MICROPY_PY_MACHINE_SPI + #include "py/mphal.h" #include "extmod/machine_spi.h" #include "modmachine.h" @@ -57,7 +61,6 @@ typedef struct _machine_spi_obj_t { } machine_spi_obj_t; extern Sercom *sercom_instance[]; -MP_REGISTER_ROOT_POINTER(void *sercom_table[SERCOM_INST_NUM]); void common_spi_irq_handler(int spi_id) { // handle Sercom IRQ RXC @@ -270,16 +273,6 @@ STATIC void machine_sercom_deinit(mp_obj_base_t *self_in) { MP_STATE_PORT(sercom_table[self->id]) = NULL; } -void sercom_deinit_all(void) { - for (int i = 0; i < SERCOM_INST_NUM; i++) { - Sercom *spi = sercom_instance[i]; - spi->SPI.INTENCLR.reg = 0xff; - sercom_register_irq(i, NULL); - sercom_enable(spi, 0); - MP_STATE_PORT(sercom_table[i]) = NULL; - } -} - STATIC void machine_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) { machine_spi_obj_t *self = (machine_spi_obj_t *)self_in; @@ -341,3 +334,5 @@ MP_DEFINE_CONST_OBJ_TYPE( protocol, &machine_spi_p, locals_dict, &mp_machine_spi_locals_dict ); + +#endif diff --git a/ports/samd/machine_uart.c b/ports/samd/machine_uart.c index ec1b42de9e20c..8028d8872dc57 100644 --- a/ports/samd/machine_uart.c +++ b/ports/samd/machine_uart.c @@ -25,6 +25,9 @@ * THE SOFTWARE. */ #include "py/runtime.h" + +#if MICROPY_PY_MACHINE_I2C || MICROPY_PY_MACHINE_SPI || MICROPY_PY_MACHINE_UART + #include "py/mphal.h" #include "py/stream.h" #include "py/ringbuf.h" @@ -59,6 +62,28 @@ typedef struct _machine_uart_obj_t { } machine_uart_obj_t; Sercom *sercom_instance[] = SERCOM_INSTS; +MP_REGISTER_ROOT_POINTER(void *sercom_table[SERCOM_INST_NUM]); + +// Common Sercom functions used by all Serial devices +void sercom_enable(Sercom *uart, int state) { + uart->USART.CTRLA.bit.ENABLE = state; // Set the state on/off + // Wait for the Registers to update. + while (uart->USART.SYNCBUSY.bit.ENABLE) { + } +} + +void sercom_deinit_all(void) { + for (int i = 0; i < SERCOM_INST_NUM; i++) { + Sercom *uart = sercom_instance[i]; + uart->USART.INTENCLR.reg = 0xff; + sercom_register_irq(i, NULL); + sercom_enable(uart, 0); + MP_STATE_PORT(sercom_table[i]) = NULL; + } +} +#endif + +#if MICROPY_PY_MACHINE_UART STATIC const char *_parity_name[] = {"None", "", "0", "1"}; // Is defined as 0, 2, 3 @@ -105,13 +130,6 @@ void common_uart_irq_handler(int uart_id) { } } -void sercom_enable(Sercom *uart, int state) { - uart->USART.CTRLA.bit.ENABLE = state; // Set the state on/off - // Wait for the Registers to update. - while (uart->USART.SYNCBUSY.bit.ENABLE) { - } -} - STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, " @@ -544,3 +562,4 @@ MP_DEFINE_CONST_OBJ_TYPE( protocol, &uart_stream_p, locals_dict, &machine_uart_locals_dict ); +#endif diff --git a/ports/samd/machine_wdt.c b/ports/samd/machine_wdt.c index c0fbfdbfbc7d3..d7dcfcf54e673 100644 --- a/ports/samd/machine_wdt.c +++ b/ports/samd/machine_wdt.c @@ -36,7 +36,14 @@ typedef struct _machine_wdt_obj_t { mp_obj_base_t base; } machine_wdt_obj_t; -extern mp_int_t log2i(mp_int_t num); +// Calculate the floor value of log2(n) +mp_int_t log2i(mp_int_t num) { + mp_int_t res = 0; + for (; num > 1; num >>= 1) { + res += 1; + } + return res; +} STATIC const machine_wdt_obj_t machine_wdt = {{&machine_wdt_type}}; diff --git a/ports/samd/main.c b/ports/samd/main.c index 1e30df13d40d9..74eb5e328526b 100644 --- a/ports/samd/main.c +++ b/ports/samd/main.c @@ -81,12 +81,18 @@ void samd_main(void) { soft_reset_exit: mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n"); + #if MICROPY_PY_MACHINE_ADC adc_deinit_all(); + #endif pin_irq_deinit_all(); + #if MICROPY_PY_MACHINE_PWM pwm_deinit_all(); + #endif soft_timer_deinit(); gc_sweep_all(); + #if MICROPY_PY_MACHINE_I2C || MICROPY_PY_MACHINE_SPI || MICROPY_PY_MACHINE_UART sercom_deinit_all(); + #endif mp_deinit(); } } diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index a2ef34b99d3d6..58ca895b45b6c 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -234,17 +234,33 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) }, { MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) }, + #if MICROPY_PY_MACHINE_ADC { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) }, + #endif + #if MICROPY_PY_MACHINE_DAC { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&machine_dac_type) }, + #endif { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, { MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) }, + #if MICROPY_PY_MACHINE_PWM { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) }, + #endif + #if MICROPY_PY_MACHINE_SOFTI2C { MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) }, + #endif + #if MICROPY_PY_MACHINE_I2C { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, + #endif + #if MICROPY_PY_MACHINE_SOFTSPI { MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) }, + #endif + #if MICROPY_PY_MACHINE_SPI { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) }, + #endif { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) }, + #if MICROPY_PY_MACHINE_UART { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, + #endif { MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&machine_wdt_type) }, #if MICROPY_PY_MACHINE_RTC { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) }, @@ -254,7 +270,9 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) }, { MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) }, { MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) }, + #if MICROPY_PY_MACHINE_PULSE { MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) }, + #endif { MP_ROM_QSTR(MP_QSTR_lightsleep), MP_ROM_PTR(&machine_lightsleep_obj) }, { MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_lightsleep_obj) }, diff --git a/ports/samd/modmachine.h b/ports/samd/modmachine.h index 8b3059d9fc716..b3ba44039a8d4 100644 --- a/ports/samd/modmachine.h +++ b/ports/samd/modmachine.h @@ -29,14 +29,26 @@ #include "py/obj.h" #include "shared/timeutils/timeutils.h" +#if MICROPY_PY_MACHINE_ADC extern const mp_obj_type_t machine_adc_type; +#endif +#if MICROPY_PY_MACHINE_DAC extern const mp_obj_type_t machine_dac_type; +#endif +#if MICROPY_PY_MACHINE_I2C extern const mp_obj_type_t machine_i2c_type; +#endif extern const mp_obj_type_t machine_pin_type; +#if MICROPY_PY_MACHINE_PWM extern const mp_obj_type_t machine_pwm_type; +#endif +#if MICROPY_PY_MACHINE_SPI extern const mp_obj_type_t machine_spi_type; +#endif extern const mp_obj_type_t machine_timer_type; +#if MICROPY_PY_MACHINE_UART extern const mp_obj_type_t machine_uart_type; +#endif extern const mp_obj_type_t machine_wdt_type; #if MICROPY_PY_MACHINE_RTC extern const mp_obj_type_t machine_rtc_type; diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index 3b89ee082bfd4..bf03b5f7bd681 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -94,18 +94,39 @@ #define MICROPY_PY_URANDOM (1) #define MICROPY_PY_UZLIB (1) #define MICROPY_PY_UASYNCIO (1) -#define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_RTC (1) -#define MICROPY_PY_MACHINE_SOFTI2C (1) +#ifndef MICROPY_PY_MACHINE_ADC +#define MICROPY_PY_MACHINE_ADC (1) +#endif +#ifndef MICROPY_PY_MACHINE_DAC +#define MICROPY_PY_MACHINE_DAC (1) +#endif +#ifndef MICROPY_PY_MACHINE_I2C +#define MICROPY_PY_MACHINE_I2C (1) +#endif +#ifndef MICROPY_PY_MACHINE_SPI #define MICROPY_PY_MACHINE_SPI (1) +#endif +#ifndef MICROPY_PY_MACHINE_SOFTI2C +#define MICROPY_PY_MACHINE_SOFTI2C (1) +#endif +#ifndef MICROPY_PY_MACHINE_SOFTSPI #define MICROPY_PY_MACHINE_SOFTSPI (1) +#endif +#ifndef MICROPY_PY_MACHINE_UART +#define MICROPY_PY_MACHINE_UART (1) +#endif #define MICROPY_PY_MACHINE_TIMER (1) #define MICROPY_SOFT_TIMER_TICKS_MS systick_ms #define MICROPY_PY_OS_DUPTERM (3) #define MICROPY_PY_MACHINE_BITSTREAM (1) +#ifndef MICROPY_PY_MACHINE_PULSE #define MICROPY_PY_MACHINE_PULSE (1) +#endif +#ifndef MICROPY_PY_MACHINE_PWM #define MICROPY_PY_MACHINE_PWM (1) #define MICROPY_PY_MACHINE_PWM_INCLUDEFILE "ports/samd/machine_pwm.c" +#endif #define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new #define MP_STATE_PORT MP_STATE_VM diff --git a/ports/samd/pin_af.c b/ports/samd/pin_af.c index 15743d1dfe6e4..419b81477601c 100644 --- a/ports/samd/pin_af.c +++ b/ports/samd/pin_af.c @@ -121,6 +121,7 @@ const char *pin_name(int id) { return "-"; } +#if MICROPY_PY_MACHINE_I2C || MICROPY_PY_MACHINE_SPI || MICROPY_PY_MACHINE_UART // Test, whether the given pin is defined and has signals for sercom. // If that applies return the alt_fct and pad_nr. // If not, an error will be raised. @@ -135,7 +136,9 @@ sercom_pad_config_t get_sercom_config(int pin_id, uint8_t sercom_nr) { mp_raise_ValueError(MP_ERROR_TEXT("wrong serial device")); } } +#endif +#if MICROPY_PY_MACHINE_ADC // Test, whether the given pin is defined as ADC. // If that applies return the adc instance and channel. // If not, an error will be raised. @@ -152,6 +155,9 @@ adc_config_t get_adc_config(int pin_id, int32_t flag) { mp_raise_ValueError(MP_ERROR_TEXT("ADC pin used")); } } +#endif + +#if MICROPY_PY_MACHINE_PWM // Test, whether the given pin is defined and has signals for pwm. // If that applies return the alt_fct, tcc number and channel number. @@ -188,3 +194,5 @@ pwm_config_t get_pwm_config(int pin_id, int wanted_dev, uint8_t device_status[]) } mp_raise_ValueError(MP_ERROR_TEXT("not a PWM Pin")); } + +#endif From 984456731b01a3ee0eb84db790f1b0dbbd2cd98e Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 5 May 2023 20:46:32 +0200 Subject: [PATCH 09/10] samd/boards/SEEED_WIO_TERMINAL: Rename two pins starting with a digit. So the names don't start with a digit, which isn't allowed in Python. Signed-off-by: robert-hh --- ports/samd/boards/SEEED_WIO_TERMINAL/pins.csv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/samd/boards/SEEED_WIO_TERMINAL/pins.csv b/ports/samd/boards/SEEED_WIO_TERMINAL/pins.csv index 622de4c6c5bb2..55cbb5bf0492d 100644 --- a/ports/samd/boards/SEEED_WIO_TERMINAL/pins.csv +++ b/ports/samd/boards/SEEED_WIO_TERMINAL/pins.csv @@ -20,8 +20,8 @@ PIN_PD20,SWITCH_U PIN_PC26,BUTTON_1 PIN_PC27,BUTTON_2 PIN_PC28,BUTTON_3 -PIN_PC14,5V_ENABLE -PIN_PC15,3V3_ENABLE +PIN_PC14,ENABLE_5V +PIN_PC15,ENABLE_3V3 PIN_PB26,TX PIN_PB27,RX PIN_PA13,SDA0 From 2a38531d73a9795c479635162c0609f6328e088c Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 12 May 2023 11:04:04 +0200 Subject: [PATCH 10/10] samd/mcu: Reduce the startup time after hard reset. With Crystal: set the crystal startup wait time to 1 second. It was 2 seconds before, and that seeemed too long. With USB-Sync: scan for up to 1 second for the USB to be registered and carry on with boot as soon as it it. Before, the code just waited for 500ms. Side change: improve related comments. Signed-off-by: robert-hh --- ports/samd/mcu/samd21/clock_config.c | 41 +++++++++++++-------- ports/samd/mcu/samd51/clock_config.c | 55 +++++++++++++++------------- 2 files changed, 56 insertions(+), 40 deletions(-) diff --git a/ports/samd/mcu/samd21/clock_config.c b/ports/samd/mcu/samd21/clock_config.c index 4c05dd7cc71fe..d84ee526767c9 100644 --- a/ports/samd/mcu/samd21/clock_config.c +++ b/ports/samd/mcu/samd21/clock_config.c @@ -52,7 +52,7 @@ uint32_t get_peripheral_freq(void) { void set_cpu_freq(uint32_t cpu_freq_arg) { - // Set 1 waitstate to be safe + // Set 1 wait state to be safe NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_MANW | NVMCTRL_CTRLB_RWS(1); int div = MAX(DFLL48M_FREQ / cpu_freq_arg, 1); @@ -75,7 +75,7 @@ void set_cpu_freq(uint32_t cpu_freq_arg) { while (GCLK->STATUS.bit.SYNCBUSY) { } // configure the FDPLL96 - // CtrlB: Set the ref ource to GCLK, set the Wakup-Fast Flag. + // CtrlB: Set the ref source to GCLK, set the Wakeup-Fast Flag. SYSCTRL->DPLLCTRLB.reg = SYSCTRL_DPLLCTRLB_REFCLK_GCLK | SYSCTRL_DPLLCTRLB_WUF; // Set the FDPLL ratio and enable the DPLL. int ldr = cpu_freq / FDPLL_REF_FREQ; @@ -106,25 +106,36 @@ void set_cpu_freq(uint32_t cpu_freq_arg) { while (GCLK->STATUS.bit.SYNCBUSY) { } } - // Set 0 waitstates for slower CPU clock + // Set 0 wait states for slower CPU clock NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_MANW | NVMCTRL_CTRLB_RWS(cpu_freq > 24000000 ? 1 : 0); SysTick_Config(cpu_freq / 1000); } void check_usb_recovery_mode(void) { #if !MICROPY_HW_XOSC32K - mp_hal_delay_ms(500); - // Check USB status. If not connected, switch DFLL48M back to open loop - if (USB->DEVICE.DeviceEndpoint[0].EPCFG.reg == 0) { - // Set/keep the open loop mode of the device. - SYSCTRL->DFLLVAL.reg = dfll48m_calibration; - SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_CCDIS | SYSCTRL_DFLLCTRL_ENABLE; + // Check USB status for up to 1 second. If not connected, + // switch DFLL48M back to open loop + for (int i = 0; i < 100; i++) { + if (USB->DEVICE.DeviceEndpoint[0].EPCFG.reg != 0) { + return; + } + mp_hal_delay_ms(10); } + // Set/keep the open loop mode of the device. + SYSCTRL->DFLLVAL.reg = dfll48m_calibration; + SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_CCDIS | SYSCTRL_DFLLCTRL_ENABLE; #endif // MICROPY_HW_XOSC32K } // Purpose of the #defines for the clock configuration. // +// The CPU is either driven by the FDPLL96 oscillator for f >= 48MHz, +// or by the DFLL48M for lower frequencies. The FDPLL96 takes 32768 Hz +// as reference frequency, supplied through GCLK1. +// +// DFLL48M is used for the peripheral clock, e.g. for PWM, UART, SPI, I2C. +// DFLL48M is either free running, or controlled by the 32kHz crystal, or +// Synchronized with the USB clock. // Both CPU and peripheral devices are clocked by the DFLL48M clock. // DFLL48M is either free running, or controlled by the 32kHz crystal, or // Synchronized with the USB clock. @@ -136,7 +147,7 @@ void check_usb_recovery_mode(void) { // The crystal is used, unless MICROPY_HW_MCU_OSC32KULP is set. // In that case GCLK1 (and the CPU clock) is driven by the 32K Low power oscillator. // The reason for offering this option is a design flaw of the Adafruit -// Feather boards, where the RGB Led and Debug signals interfere with the +// Feather boards, where the RGB LED and Debug signals interfere with the // crystal, causing the CPU to fail if it is driven by the crystal. // // If MICROPY_HW_XOSC32K = 0, the 32kHz signal for GCLK1 (and the CPU) is @@ -144,10 +155,10 @@ void check_usb_recovery_mode(void) { // // If MICROPY_HW_DFLL_USB_SYNC = 0, the DFLL48M oscillator is free running using // the pre-configured trim values. In that mode, the peripheral clock is -// not exactly 48Mhz and has a substantional temperature drift. +// not exactly 48Mhz and has a substitutional temperature drift. // // If MICROPY_HW_DFLL_USB_SYNC = 1, the DFLL48 is synchronized with the 1 kHz USB sync -// signal. If after boot there is no USB sync within 500ms, the configuration falls +// signal. If after boot there is no USB sync within 1000 ms, the configuration falls // back to a free running 48Mhz oscillator. // // In all modes, the 48MHz signal has a substantial jitter, largest when @@ -181,7 +192,7 @@ void init_clocks(uint32_t cpu_freq) { NVMCTRL->CTRLB.bit.RWS = 1; // 1 read wait state for 48MHz #if MICROPY_HW_XOSC32K - // Set up OSC32K according datasheet 17.6.3 + // Set up OSC32K according data sheet 17.6.3 SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_STARTUP(0x3) | SYSCTRL_XOSC32K_EN32K | SYSCTRL_XOSC32K_XTALEN; SYSCTRL->XOSC32K.bit.ENABLE = 1; @@ -211,12 +222,12 @@ void init_clocks(uint32_t cpu_freq) { while (GCLK->STATUS.bit.SYNCBUSY) { } - // Enable access to the DFLLCTRL reg acc. to Errata 1.2.1 + // Enable access to the DFLLCTRL register according to Errata 1.2.1 SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE; while (SYSCTRL->PCLKSR.bit.DFLLRDY == 0) { } // Step 2: Set the coarse and fine values. - // Get the coarse value from the calib data. In case it is not set, + // Get the coarse value from the calibration data. In case it is not set, // set a midrange value. uint32_t coarse = (*((uint32_t *)FUSES_DFLL48M_COARSE_CAL_ADDR) & FUSES_DFLL48M_COARSE_CAL_Msk) >> FUSES_DFLL48M_COARSE_CAL_Pos; diff --git a/ports/samd/mcu/samd51/clock_config.c b/ports/samd/mcu/samd51/clock_config.c index 50912b77ed8df..b30cc46f24596 100644 --- a/ports/samd/mcu/samd51/clock_config.c +++ b/ports/samd/mcu/samd51/clock_config.c @@ -117,27 +117,32 @@ void set_cpu_freq(uint32_t cpu_freq_arg) { void check_usb_recovery_mode(void) { #if !MICROPY_HW_XOSC32K - mp_hal_delay_ms(500); - // Check USB status. If not connected, switch DFLL48M back to open loop - if (USB->DEVICE.DeviceEndpoint[0].EPCFG.reg == 0) { - // as per Errata 2.8.3 - OSCCTRL->DFLLMUL.reg = 0; - while (OSCCTRL->DFLLSYNC.bit.DFLLMUL == 1) { - } - // Set the mode to open loop mode - OSCCTRL->DFLLCTRLB.reg = 0; - while (OSCCTRL->DFLLSYNC.bit.DFLLCTRLB == 1) { - } - OSCCTRL->DFLLCTRLA.reg = OSCCTRL_DFLLCTRLA_RUNSTDBY | OSCCTRL_DFLLCTRLA_ENABLE; - while (OSCCTRL->DFLLSYNC.bit.ENABLE == 1) { - } - OSCCTRL->DFLLVAL.reg = dfll48m_calibration; // Reload DFLLVAL register - while (OSCCTRL->DFLLSYNC.bit.DFLLVAL == 1) { - } - // Set the mode to open loop mode - OSCCTRL->DFLLCTRLB.reg = 0; - while (OSCCTRL->DFLLSYNC.bit.DFLLCTRLB == 1) { + // Check USB status for up to 1 second. If not connected, + // switch DFLL48M back to open loop + for (int i = 0; i < 100; i++) { + if (USB->DEVICE.DeviceEndpoint[0].EPCFG.reg != 0) { + return; } + mp_hal_delay_ms(10); + } + // No connection. Switch back to open loop mode. + // as per Errata 2.8.3 + OSCCTRL->DFLLMUL.reg = 0; + while (OSCCTRL->DFLLSYNC.bit.DFLLMUL == 1) { + } + // Set the mode to open loop mode + OSCCTRL->DFLLCTRLB.reg = 0; + while (OSCCTRL->DFLLSYNC.bit.DFLLCTRLB == 1) { + } + OSCCTRL->DFLLCTRLA.reg = OSCCTRL_DFLLCTRLA_RUNSTDBY | OSCCTRL_DFLLCTRLA_ENABLE; + while (OSCCTRL->DFLLSYNC.bit.ENABLE == 1) { + } + OSCCTRL->DFLLVAL.reg = dfll48m_calibration; // Reload DFLLVAL register + while (OSCCTRL->DFLLSYNC.bit.DFLLVAL == 1) { + } + // Set the mode to open loop mode + OSCCTRL->DFLLCTRLB.reg = 0; + while (OSCCTRL->DFLLSYNC.bit.DFLLCTRLB == 1) { } #endif // MICROPY_HW_XOSC32K } @@ -169,10 +174,10 @@ void check_usb_recovery_mode(void) { // // If MICROPY_HW_DFLL_USB_SYNC = 0, the DFLL48M oscillator is free running using // the pre-configured trim values. In that mode, the peripheral clock is -// not exactly 48Mhz and has a substantional temperature drift. +// not exactly 48Mhz and has a substitutional temperature drift. // // If MICROPY_HW_DFLL_USB_SYNC = 1, the DFLL48 is synchronized with the 1 kHz USB sync -// signal. If after boot there is no USB sync within 500ms, the configuration falls +// signal. If after boot there is no USB sync within 1000 ms, the configuration falls // back to a free running 48Mhz oscillator. // // In all modes, the 48MHz signal has a substantial jitter, largest when @@ -223,16 +228,16 @@ void init_clocks(uint32_t cpu_freq) { OSC32KCTRL->RTCCTRL.reg = OSC32KCTRL_RTCCTRL_RTCSEL_XOSC1K; // Setup XOSC32K OSC32KCTRL->INTFLAG.reg = OSC32KCTRL_INTFLAG_XOSC32KRDY | OSC32KCTRL_INTFLAG_XOSC32KFAIL; - OSC32KCTRL->CFDCTRL.bit.CFDEN = 1; // Fall back to internal Osc on crystal fail + OSC32KCTRL->CFDCTRL.bit.CFDEN = 1; // Fall back to internal oscillator on crystal fail OSC32KCTRL->XOSC32K.reg = OSC32KCTRL_XOSC32K_CGM_HS | OSC32KCTRL_XOSC32K_XTALEN | OSC32KCTRL_XOSC32K_EN32K | OSC32KCTRL_XOSC32K_EN1K | OSC32KCTRL_XOSC32K_RUNSTDBY | - OSC32KCTRL_XOSC32K_STARTUP(4) | + OSC32KCTRL_XOSC32K_STARTUP(3) | OSC32KCTRL_XOSC32K_ENABLE; - // make sure osc32kcrtl is ready + // Wait until the oscillator is running and stable while (OSC32KCTRL->STATUS.bit.XOSC32KRDY == 0) { } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy