From 5c6c60878e373bf0dc4fc16c74b44054f9567a08 Mon Sep 17 00:00:00 2001 From: Brandon Date: Sun, 4 Jan 2026 19:32:20 -0800 Subject: [PATCH 01/23] ports: analog: Remove FIXME comments from MAX32690 linkerscript Signed-off-by: Brandon --- ports/analog/linking/max32690_cktpy.ld | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/ports/analog/linking/max32690_cktpy.ld b/ports/analog/linking/max32690_cktpy.ld index 9b32121a135..89326e282ac 100644 --- a/ports/analog/linking/max32690_cktpy.ld +++ b/ports/analog/linking/max32690_cktpy.ld @@ -22,29 +22,12 @@ SECTIONS { KEEP(*(.rom_handlers*)) } > ROM - - /** FIXME: can't place this in its own section for some reason - * system doesn't exit ROM code unless *(.isr_vector) - * is placed in the beginning of .text, - * even if .text is moved upward and *(.isr_vector) is - * placed at 0x10000000. - **/ - - /* Place ISR vector in a separate flash section */ - /* .isr_vector : */ - /* { */ - /* ISR Vector beginning of .text */ - /* KEEP(*(.isr_vector)) */ - /* KEEP(*(.isr_vector*)) */ - /* } > FLASH_ISR */ - .text : { . = ALIGN(4); _text = .; /* ISR Vector beginning of .text */ - /** fixme: may want to move this to FLASH_ISR long-term */ KEEP(*(.isr_vector)) KEEP(*(.isr_vector*)) From 24397df1b7582ce1f76ef5d0b101542148e8ecb9 Mon Sep 17 00:00:00 2001 From: Brandon Date: Sun, 4 Jan 2026 22:11:55 -0800 Subject: [PATCH 02/23] ports: analog: Fix flash overlow bug in max32690 linkerscript Signed-off-by: Brandon --- ports/analog/linking/max32690_cktpy.ld | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ports/analog/linking/max32690_cktpy.ld b/ports/analog/linking/max32690_cktpy.ld index 89326e282ac..4aac33fef9c 100644 --- a/ports/analog/linking/max32690_cktpy.ld +++ b/ports/analog/linking/max32690_cktpy.ld @@ -5,15 +5,18 @@ * SPDX-License-Identifier: MIT */ +/* + * FLASH_FIRMWARE: 3072 KiB - 128 KiB = 2944 KiB + * + * Start & Size for FLASH_FIRMWARE and RAM MUST be raw numbers + * b/c FLASH_FIMRWARE is parsed with Python build_memory_info.py + */ MEMORY { ROM (rx) : ORIGIN = 0x00000000, LENGTH = 128K - FLASH (rx) : ORIGIN = 0x10000000, LENGTH = 3M - FLASH_FIRMWARE (rx) : ORIGIN = 0x10000000, LENGTH = 2992K + FLASH_FIRMWARE (rx) : ORIGIN = 0x10000000, LENGTH = 2944K FLASH_FS (rx) : ORIGIN = 0x102E0000, LENGTH = 128K RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 1M } -/* Minimum flash page is 16K */ -/* FLASH FIRMWARE: 3072K [3MB] - 16K - 64K = 2992K */ SECTIONS { .rom : From 86b310258fe1090de8977816b3b46c94988e608a Mon Sep 17 00:00:00 2001 From: Brandon Date: Mon, 5 Jan 2026 00:09:50 -0800 Subject: [PATCH 03/23] ports: analog: Update internal_flash.c to allow for multiple banks Signed-off-by: Brandon --- ports/analog/supervisor/internal_flash.c | 84 +++++++++++++----------- 1 file changed, 44 insertions(+), 40 deletions(-) diff --git a/ports/analog/supervisor/internal_flash.c b/ports/analog/supervisor/internal_flash.c index 8518b235566..45a454919f8 100644 --- a/ports/analog/supervisor/internal_flash.c +++ b/ports/analog/supervisor/internal_flash.c @@ -57,7 +57,7 @@ typedef struct { const uint32_t num_sectors; } flash_layout_t; -#ifdef MAX32690 +#if defined(MAX32690) // struct layout is the actual layout of flash // FS Code will use INTERNAL_FLASH_FILESYSTEM_START_ADDR // and won't conflict with ISR vector in first 16 KiB of flash @@ -67,7 +67,21 @@ static const flash_layout_t flash_layout[] = { }; // must be able to hold a full page (for re-writing upon erase) static uint32_t page_buffer[FLASH_PAGE_SIZE / 4] = {0x0}; - +#elif defined(MAX32650) +static const flash_layout_t flash_layout[] = { + { 0x10000000, FLASH_PAGE_SIZE, 192}, +}; +// must be able to hold a full page (for re-writing upon erase) +static uint32_t page_buffer[FLASH_PAGE_SIZE / 4] = {0x0}; +#elif defined(MAX32666) +// MAX32666 has two flash banks, but we do not actually need to +// treat them separately +static const flash_layout_t flash_layout[] = { + { 0x10000000, FLASH_PAGE_SIZE, 64}, + { 0x10080000, FLASH_PAGE_SIZE, 64}, +}; +// must be able to hold a full page (for re-writing upon erase) +static uint32_t page_buffer[FLASH_PAGE_SIZE / 4] = {0x0}; #else #error "Invalid BOARD. Please set BOARD equal to any board under 'boards/'." #endif @@ -82,44 +96,28 @@ static inline int32_t block2addr(uint32_t block) { // Get index, start addr, & size of the flash sector where addr lies int flash_get_sector_info(uint32_t addr, uint32_t *start_addr, uint32_t *size) { - // This function should return -1 in the event of errors. - if (addr >= flash_layout[0].base_addr) { - uint32_t sector_index = 0; - if (MP_ARRAY_SIZE(flash_layout) == 1) { - sector_index = (addr - flash_layout[0].base_addr) / flash_layout[0].sector_size; - if (sector_index >= flash_layout[0].num_sectors) { - return -1; // addr is not in flash - } - if (start_addr) { - *start_addr = flash_layout[0].base_addr + (sector_index * flash_layout[0].sector_size); - } else { - return -1; // start_addr is NULL - } - if (size) { - *size = flash_layout[0].sector_size; - } else { - return -1; // size is NULL - } - return sector_index; - } + if (start_addr == NULL) { + return -1; + } - // algorithm for multiple flash sections - for (uint8_t i = 0; i < MP_ARRAY_SIZE(flash_layout); ++i) { - for (uint8_t j = 0; j < flash_layout[i].num_sectors; ++j) { - uint32_t sector_start_next = flash_layout[i].base_addr - + (j + 1) * flash_layout[i].sector_size; - if (addr < sector_start_next) { - if (start_addr) { - *start_addr = flash_layout[i].base_addr - + j * flash_layout[i].sector_size; - } - if (size) { - *size = flash_layout[i].sector_size; - } - return sector_index; - } - ++sector_index; - } + if (size == NULL) { + return -1; + } + + // Search flash layout for a hit + uint32_t sector_index = 0; + for (int i = 0; i < MP_ARRAY_SIZE(flash_layout); ++i) { + flash_layout_t bank = flash_layout[i]; + + // Determine if the flash bank is a hit for this address + if ((addr >= bank.base_addr) && + (addr < bank.base_addr + bank.sector_size * bank.num_sectors) + ) { + // Assign the sector index assuming uniform sector sizes + sector_index = i * bank.num_sectors + ((addr - bank.base_addr) / bank.sector_size); + *start_addr = flash_layout[0].base_addr + (sector_index * bank.sector_size); + *size = flash_layout[i].sector_size; + return sector_index; } } return -1; @@ -141,7 +139,7 @@ uint32_t supervisor_flash_get_block_count(void) { void port_internal_flash_flush(void) { // Flush all instruction cache - // ME18 has bug where top-level sysctrl flush bit only works one. + // ME18 has bug where top-level sysctrl flush bit only works once. // Have to use low-level flush bits for each ICC instance. MXC_ICC_Flush(MXC_ICC0); MXC_ICC_Flush(MXC_ICC1); @@ -213,6 +211,9 @@ mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t block_num, if (error != E_NO_ERROR) { // lock flash & reset MXC_FLC0->ctrl = (MXC_FLC0->ctrl & ~MXC_F_FLC_REVA_CTRL_UNLOCK) | MXC_S_FLC_REVA_CTRL_UNLOCK_LOCKED; + #if defined(MAX32666) + MXC_FLC1->ctrl = (MXC_FLC1->ctrl & ~MXC_F_FLC_REVA_CTRL_UNLOCK) | MXC_S_FLC_REVA_CTRL_UNLOCK_LOCKED; + #endif reset_into_safe_mode(SAFE_MODE_FLASH_WRITE_FAIL); } @@ -228,6 +229,9 @@ mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t block_num, if (error != E_NO_ERROR) { // lock flash & reset MXC_FLC0->ctrl = (MXC_FLC0->ctrl & ~MXC_F_FLC_REVA_CTRL_UNLOCK) | MXC_S_FLC_REVA_CTRL_UNLOCK_LOCKED; + #if defined(MAX32666) + MXC_FLC1->ctrl = (MXC_FLC1->ctrl & ~MXC_F_FLC_REVA_CTRL_UNLOCK) | MXC_S_FLC_REVA_CTRL_UNLOCK_LOCKED; + #endif reset_into_safe_mode(SAFE_MODE_FLASH_WRITE_FAIL); } From 014ae00df649213d06b82bd15ee098701a65810b Mon Sep 17 00:00:00 2001 From: Brandon Date: Mon, 5 Jan 2026 23:46:40 -0800 Subject: [PATCH 04/23] ports: analog: Remove device-specific includes from core modules Signed-off-by: Brandon --- ports/analog/common-hal/microcontroller/__init__.c | 2 +- ports/analog/supervisor/usb.c | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/ports/analog/common-hal/microcontroller/__init__.c b/ports/analog/common-hal/microcontroller/__init__.c index 207ddbe52f3..dd7c095ffc3 100644 --- a/ports/analog/common-hal/microcontroller/__init__.c +++ b/ports/analog/common-hal/microcontroller/__init__.c @@ -22,7 +22,7 @@ #include "supervisor/shared/safe_mode.h" -#include "max32690.h" +#include "max32_port.h" #include "mxc_delay.h" /** NOTE: It is not advised to directly include the below! diff --git a/ports/analog/supervisor/usb.c b/ports/analog/supervisor/usb.c index 1624359ab51..803569cac09 100644 --- a/ports/analog/supervisor/usb.c +++ b/ports/analog/supervisor/usb.c @@ -13,9 +13,7 @@ #include "lib/tinyusb/src/device/usbd.h" // max32 includes -#include "mxc_sys.h" -#include "gcr_regs.h" -#include "mcr_regs.h" +#include "max32_port.h" void init_usb_hardware(void) { // USB GPIOs are non-configurable on MAX32 devices From 4c05ec91919e398361dc6c160094bbe0b197e673 Mon Sep 17 00:00:00 2001 From: Brandon Date: Mon, 5 Jan 2026 23:50:50 -0800 Subject: [PATCH 05/23] ports: analog: Add new die types to Makefile Signed-off-by: Brandon --- ports/analog/Makefile | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/ports/analog/Makefile b/ports/analog/Makefile index c81280e11ab..d37d2c2bf76 100644 --- a/ports/analog/Makefile +++ b/ports/analog/Makefile @@ -21,7 +21,6 @@ MCU_SERIES_UPPER := $(shell echo $(MCU_SERIES) | tr '[:lower:]' '[:upper:]') MCU_VARIANT_LOWER := $(shell echo $(MCU_VARIANT) | tr '[:upper:]' '[:lower:]') MCU_VARIANT_UPPER := $(shell echo $(MCU_VARIANT) | tr '[:lower:]' '[:upper:]') - # ******************************************************************************* #### MSDK INCLUDES #### # Necessary for msdk makefiles @@ -36,6 +35,17 @@ ADI_PERIPH = $(MSDK_ROOT)/Libraries/PeriphDrivers ADI_MISC_DRIVERS_DIR ?= $(MSDK_LIBS)/MiscDrivers ADI_BOARD_DIR = $(MSDK_LIBS)/Boards/$(MCU_VARIANT_UPPER)/$(BOARD) +# Set die type +ifeq ($(MCU_VARIANT_LOWER),max32690) +DIE_TYPE=me18 +else ifeq ($(MCU_VARIANT_LOWER),max32650) +DIE_TYPE=me10 +else ifeq ($(MCU_VARIANT_LOWER),max32665) +DIE_TYPE=me14 +else +DIE_TYPE=me18 +endif + # For debugging the build ifneq ($(BUILD_VERBOSE),"") $(info MSDK_ROOT is $(MSDK_ROOT)) @@ -45,6 +55,8 @@ $(info ADI_PERIPH is $(ADI_PERIPH)) $(info ADI_MISC_DRIVERS_DIR is $(ADI_MISC_DRIVERS_DIR)) $(info ADI_BOARD_DIR is $(ADI_BOARD_DIR)) $(info MAXIM_PATH is $(MAXIM_PATH)) +$(info MCU_VARIANT_LOWER is $(MCU_VARIANT_LOWER)) +$(info DIE_TYPE is $(DIE_TYPE)) endif # ----------------- @@ -54,11 +66,6 @@ endif # default to me18 for max32690 # more info: # https://analogdevicesinc.github.io/msdk//USERGUIDE/#die-types-to-part-numbers -ifeq ($(MCU_VARIANT_LOWER), "max32690") -DIE_TYPE=me18 -else -DIE_TYPE=me18 -endif PERIPH_SRC = $(ADI_PERIPH)/Source PERIPH_INC = $(ADI_PERIPH)/Include/$(MCU_VARIANT_UPPER) @@ -131,6 +138,23 @@ SRC_MAX32 += \ $(PERIPH_SRC)/SPI/spi_$(DIE_TYPE).c \ $(PERIPH_SRC)/SPI/spi_reva1.c +# Small source correction for ME10 (MAX32650) +ifeq ($(DIE_TYPE),me10) +SRC_MAX32 := $(filter-out \ + $(PERIPH_SRC)/CTB/ctb_reva.c \ + $(PERIPH_SRC)/CTB/ctb_common.c \ + $(PERIPH_SRC)/CTB/ctb_me10.c, \ + $(SRC_MAX32)) +endif + +ifeq ($(DIE_TYPE),me14) +SRC_MAX32 := $(filter-out \ + $(PERIPH_SRC)/CTB/ctb_reva.c \ + $(PERIPH_SRC)/CTB/ctb_common.c \ + $(PERIPH_SRC)/CTB/ctb_me14.c, \ + $(SRC_MAX32)) +endif + SRC_C += $(SRC_MAX32) \ boards/$(BOARD)/board.c \ boards/$(BOARD)/pins.c \ From 10a32a578cb08f1dd71dcc8e6c67a62c5d04d718 Mon Sep 17 00:00:00 2001 From: Brandon Date: Mon, 5 Jan 2026 23:55:50 -0800 Subject: [PATCH 06/23] ports: analog: Add MAX32650 & MAX32666 to max32_port.h - Add include entries for MAX32650 and MAX32666 - Rename MAX32666 macro to MAX32665 to be compatible with MSDK naming and GNU Make variables from MSDK. Signed-off-by: Brandon --- ports/analog/max32_port.h | 22 +++++++++++++++++++++- ports/analog/supervisor/internal_flash.c | 2 +- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/ports/analog/max32_port.h b/ports/analog/max32_port.h index 89830e96b0a..6da703231dc 100644 --- a/ports/analog/max32_port.h +++ b/ports/analog/max32_port.h @@ -14,11 +14,11 @@ #include "mxc_device.h" #include "mxc_pins.h" #include "mxc_sys.h" -#include "mcr_regs.h" #include "gpio.h" #ifdef MAX32690 +#include "mcr_regs.h" #include "system_max32690.h" #include "max32690.h" @@ -56,6 +56,26 @@ #endif +#ifdef MAX32650 +#include "system_max32650.h" +#include "max32650.h" + +// UART Ports & pins +#include "peripherals/max32650/max32_uart.h" +#include "peripherals/max32650/max32_i2c.h" +#include "peripherals/max32650/max32_spi.h" +#endif + +#ifdef MAX32665 +#include "system_max32665.h" +#include "max32665.h" + +// UART Ports & pins +#include "peripherals/max32665/max32_uart.h" +#include "peripherals/max32665/max32_i2c.h" +#include "peripherals/max32665/max32_spi.h" +#endif + /** Linker variables defined.... * _estack: end of the stack * _ebss: end of BSS section diff --git a/ports/analog/supervisor/internal_flash.c b/ports/analog/supervisor/internal_flash.c index 45a454919f8..c20e5d78f12 100644 --- a/ports/analog/supervisor/internal_flash.c +++ b/ports/analog/supervisor/internal_flash.c @@ -73,7 +73,7 @@ static const flash_layout_t flash_layout[] = { }; // must be able to hold a full page (for re-writing upon erase) static uint32_t page_buffer[FLASH_PAGE_SIZE / 4] = {0x0}; -#elif defined(MAX32666) +#elif defined(MAX32665) // MAX32666 has two flash banks, but we do not actually need to // treat them separately static const flash_layout_t flash_layout[] = { From 2f99b4d8668f99b7075af2a65d25602385e332b0 Mon Sep 17 00:00:00 2001 From: Brandon Date: Mon, 5 Jan 2026 23:57:59 -0800 Subject: [PATCH 07/23] ports: analog: Add linkerscripts for MAX32650 & MAX32666 Signed-off-by: Brandon --- ports/analog/linking/max32650_cktpy.ld | 174 +++++++++++++++++++++++++ ports/analog/linking/max32666_cktpy.ld | 173 ++++++++++++++++++++++++ 2 files changed, 347 insertions(+) create mode 100644 ports/analog/linking/max32650_cktpy.ld create mode 100644 ports/analog/linking/max32666_cktpy.ld diff --git a/ports/analog/linking/max32650_cktpy.ld b/ports/analog/linking/max32650_cktpy.ld new file mode 100644 index 00000000000..3e72798f1dc --- /dev/null +++ b/ports/analog/linking/max32650_cktpy.ld @@ -0,0 +1,174 @@ +/** This file is part of the CircuitPython project: https://circuitpython.org +* +* SPDX-FileCopyrightText: Copyright (c) 2025 Brandon Hurst, Analog Devices Inc. +* +* SPDX-License-Identifier: MIT +*/ + +/* + * FLASH_FIRMWARE: 3072 KiB - 128 KiB = 2944 KiB + * + * Start & Size for FLASH_FIRMWARE and RAM MUST be raw numbers + * b/c FLASH_FIMRWARE is parsed with Python build_memory_info.py + */ +MEMORY { + ROM (rx) : ORIGIN = 0x00000000, LENGTH = 128K + FLASH (rx) : ORIGIN = 0x10000000, LENGTH = 3M + FLASH_FIRMWARE (rx) : ORIGIN = 0x10000000, LENGTH = 2944K + FLASH_FS (rx) : ORIGIN = 0x102E0000, LENGTH = 128K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 1M +} +/* FLASH FIRMWARE: 3072K [3MB] - 128K = 2944K */ + +SECTIONS { + .rom : + { + KEEP(*(.rom_vector*)) + KEEP(*(.rom_handlers*)) + } > ROM + + .text : + { + . = ALIGN(4); + _text = .; + + /* ISR Vector beginning of .text */ + KEEP(*(.isr_vector)) + KEEP(*(.isr_vector*)) + + . = ALIGN(4); + + /* program code; exclude RISCV code */ + EXCLUDE_FILE (*riscv.o) *(.text*) + *(.rodata*) /* read-only data: "const" */ + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + /* C++ Exception handling */ + KEEP(*(.eh_frame*)) + . = ALIGN(4); + _etext = .; + } > FLASH_FIRMWARE + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH_FIRMWARE + + /* Binary import */ + .bin_storage : + { + FILL(0xFF) + _bin_start_ = .; + KEEP(*(.bin_storage_img)) + _bin_end_ = .; + . = ALIGN(4); + } > FLASH_FIRMWARE + + /* it's used for C++ exception handling */ + /* we need to keep this to avoid overlapping */ + .ARM.exidx : + { + __exidx_start = .; + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __exidx_end = .; + } > FLASH_FIRMWARE + + .data : + { + . = ALIGN(4); + _data = .; + _sdata = .; + + *(vtable) + *(.data*) /*read-write initialized data: initialized global variable*/ + + /* These array sections are used by __libc_init_array to call static C++ constructors */ + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + /* Run the flash programming functions from SRAM */ + *(.flashprog) + + . = ALIGN(4); + _edata = .; + } > RAM AT>FLASH_FIRMWARE + __load_data = LOADADDR(.data); + + .bss : + { + . = ALIGN(4); + _sbss = .; /* Provide _sbss for Cktpy */ + _bss = .; + + *(.bss*) /*read-write zero initialized data: uninitialized global variable*/ + *(COMMON) + + . = ALIGN(4); + _ebss = .; + _ezero = .; /* Provide _ezero /_ebss for CktPython (same as ebss) */ + } > RAM + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + *(.stack*) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + + _stack = __StackTop; + _estack = __StackLimit; /* Provide _estack for CktPython */ + + .heap (COPY): + { + . = ALIGN(4); + _heap = .; + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + *(.heap*) + __HeapLimit = ABSOLUTE(__StackLimit); + } > RAM + + _eheap = __HeapLimit; + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= _ebss, "region RAM overflowed with stack") +} diff --git a/ports/analog/linking/max32666_cktpy.ld b/ports/analog/linking/max32666_cktpy.ld new file mode 100644 index 00000000000..639be448cea --- /dev/null +++ b/ports/analog/linking/max32666_cktpy.ld @@ -0,0 +1,173 @@ +/** This file is part of the CircuitPython project: https://circuitpython.org +* +* SPDX-FileCopyrightText: Copyright (c) 2025 Brandon Hurst, Analog Devices Inc. +* +* SPDX-License-Identifier: MIT +*/ + +/* + * FLASH_FIRMWARE: 1024 KiB - 128 KiB = 896 KiB + * + * Start & Size for FLASH_FIRMWARE and RAM MUST be raw numbers + * b/c FLASH_FIMRWARE is parsed with Python build_memory_info.py + */ +MEMORY { + ROM (rx) : ORIGIN = 0x00000000, LENGTH = 128K + FLASH (rx) : ORIGIN = 0x10000000, LENGTH = 1M + FLASH_FIRMWARE (rx) : ORIGIN = 0x10000000, LENGTH = 896K + FLASH_FS (rx) : ORIGIN = 0x100E0000, LENGTH = 128K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 560K +} + +SECTIONS { + .rom : + { + KEEP(*(.rom_vector*)) + KEEP(*(.rom_handlers*)) + } > ROM + + .text : + { + . = ALIGN(4); + _text = .; + + /* ISR Vector beginning of .text */ + KEEP(*(.isr_vector)) + KEEP(*(.isr_vector*)) + + . = ALIGN(4); + + /* program code; exclude RISCV code */ + EXCLUDE_FILE (*riscv.o) *(.text*) + *(.rodata*) /* read-only data: "const" */ + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + /* C++ Exception handling */ + KEEP(*(.eh_frame*)) + . = ALIGN(4); + _etext = .; + } > FLASH_FIRMWARE + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH_FIRMWARE + + /* Binary import */ + .bin_storage : + { + FILL(0xFF) + _bin_start_ = .; + KEEP(*(.bin_storage_img)) + _bin_end_ = .; + . = ALIGN(4); + } > FLASH_FIRMWARE + + /* it's used for C++ exception handling */ + /* we need to keep this to avoid overlapping */ + .ARM.exidx : + { + __exidx_start = .; + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __exidx_end = .; + } > FLASH_FIRMWARE + + .data : + { + . = ALIGN(4); + _data = .; + _sdata = .; + + *(vtable) + *(.data*) /*read-write initialized data: initialized global variable*/ + + /* These array sections are used by __libc_init_array to call static C++ constructors */ + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + /* Run the flash programming functions from SRAM */ + *(.flashprog) + + . = ALIGN(4); + _edata = .; + } > RAM AT>FLASH_FIRMWARE + __load_data = LOADADDR(.data); + + .bss : + { + . = ALIGN(4); + _sbss = .; /* Provide _sbss for Cktpy */ + _bss = .; + + *(.bss*) /*read-write zero initialized data: uninitialized global variable*/ + *(COMMON) + + . = ALIGN(4); + _ebss = .; + _ezero = .; /* Provide _ezero /_ebss for CktPython (same as ebss) */ + } > RAM + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + *(.stack*) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + + _stack = __StackTop; + _estack = __StackLimit; /* Provide _estack for CktPython */ + + .heap (COPY): + { + . = ALIGN(4); + _heap = .; + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + *(.heap*) + __HeapLimit = ABSOLUTE(__StackLimit); + } > RAM + + _eheap = __HeapLimit; + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= _ebss, "region RAM overflowed with stack") +} From 85945c1716401e13c370f6a5cf5d5d3b7a41162b Mon Sep 17 00:00:00 2001 From: Brandon Date: Mon, 5 Jan 2026 23:58:28 -0800 Subject: [PATCH 08/23] ports: analog: Add board files for MAX32650FTHR & MAX32666FTHR Signed-off-by: Brandon --- ports/analog/boards/max32650fthr/README.md | 33 +++++ ports/analog/boards/max32650fthr/board.c | 32 +++++ .../boards/max32650fthr/mpconfigboard.h | 40 ++++++ .../boards/max32650fthr/mpconfigboard.mk | 31 +++++ ports/analog/boards/max32650fthr/pins.c | 126 ++++++++++++++++++ ports/analog/boards/max32666fthr/README.md | 33 +++++ ports/analog/boards/max32666fthr/board.c | 32 +++++ .../boards/max32666fthr/mpconfigboard.h | 40 ++++++ .../boards/max32666fthr/mpconfigboard.mk | 31 +++++ ports/analog/boards/max32666fthr/pins.c | 66 +++++++++ 10 files changed, 464 insertions(+) create mode 100644 ports/analog/boards/max32650fthr/README.md create mode 100644 ports/analog/boards/max32650fthr/board.c create mode 100644 ports/analog/boards/max32650fthr/mpconfigboard.h create mode 100644 ports/analog/boards/max32650fthr/mpconfigboard.mk create mode 100644 ports/analog/boards/max32650fthr/pins.c create mode 100644 ports/analog/boards/max32666fthr/README.md create mode 100644 ports/analog/boards/max32666fthr/board.c create mode 100644 ports/analog/boards/max32666fthr/mpconfigboard.h create mode 100644 ports/analog/boards/max32666fthr/mpconfigboard.mk create mode 100644 ports/analog/boards/max32666fthr/pins.c diff --git a/ports/analog/boards/max32650fthr/README.md b/ports/analog/boards/max32650fthr/README.md new file mode 100644 index 00000000000..4069fb1e26d --- /dev/null +++ b/ports/analog/boards/max32650fthr/README.md @@ -0,0 +1,33 @@ +# MAX32650FTHR + +[TODO] + +## Onboard connectors & peripherals + +[TODO] + +## Product Resources + +[TODO] + +### Building for this board + +To build for this board, ensure you are in the `ports/analog` directory and run the following command. Note that passing in the `-jN` flag, where N is the # of cores on your machine, can speed up compile times. + +``` +make BOARD=max32650fthr +``` + +### Flashing this board + +To flash the board, run the following command if using the MAX32625PICO: + +``` +make BOARD=max32655fthr flash-msdk +``` + +If using Segger JLink, please run the following command instead: + +``` +make BOARD=max32655fthr flash-jlink +``` diff --git a/ports/analog/boards/max32650fthr/board.c b/ports/analog/boards/max32650fthr/board.c new file mode 100644 index 00000000000..76c3e7f5591 --- /dev/null +++ b/ports/analog/boards/max32650fthr/board.c @@ -0,0 +1,32 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "supervisor/port.h" +#include "mpconfigboard.h" +#include "max32_port.h" + +/***** OPTIONAL BOARD-SPECIFIC FUNCTIONS from supervisor/board.h *****/ +// DEFAULT: Using the weak-defined supervisor/shared/board.c functions + +// Initializes board related state once on start up. +void board_init(void) { +} + +// Returns true if the user initiates safe mode in a board specific way. +// Also add BOARD_USER_SAFE_MODE in mpconfigboard.h to explain the board specific +// way. +// bool board_requests_safe_mode(void); + +// Reset the state of off MCU components such as neopixels. +// void reset_board(void); + +// Deinit the board. This should put the board in deep sleep durable, low power +// state. It should not prevent the user access method from working (such as +// disabling USB, BLE or flash) because CircuitPython may continue to run. +// void board_deinit(void); + +/*******************************************************************/ diff --git a/ports/analog/boards/max32650fthr/mpconfigboard.h b/ports/analog/boards/max32650fthr/mpconfigboard.h new file mode 100644 index 00000000000..bdcfff24148 --- /dev/null +++ b/ports/analog/boards/max32650fthr/mpconfigboard.h @@ -0,0 +1,40 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices Inc. +// +// SPDX-License-Identifier: MIT + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2016 Glenn Ruben Bakke +// SPDX-FileCopyrightText: Copyright (c) 2018 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "MAX32650FTHR" +#define MICROPY_HW_MCU_NAME "max32650" + +#define FLASH_SIZE (0x300000) // 3MiB +#define FLASH_PAGE_SIZE (0x4000) // 16384 byte pages (16 KiB) + +#define BOARD_HAS_CRYSTAL 1 +#define NUM_GPIO_PORTS 4 +#define CONSOLE_UART MXC_UART0 + +// #if INTERNAL_FLASH_FILESYSTEM +#define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_START_ADDR (0x102E0000) // for MAX32650 +#define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE (128 * 1024) // 128K + +#define MAX32_FLASH_SIZE 0x300000 // 3 MiB +#define INTERNAL_FLASH_FILESYSTEM_SIZE CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE +#define INTERNAL_FLASH_FILESYSTEM_START_ADDR 0x102E0000 // Load into the last MiB of code/data storage + +// #else +// #define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE (0) +// #endif + + #define MICROPY_HW_LED_STATUS (&pin_P1_18) diff --git a/ports/analog/boards/max32650fthr/mpconfigboard.mk b/ports/analog/boards/max32650fthr/mpconfigboard.mk new file mode 100644 index 00000000000..1164e616484 --- /dev/null +++ b/ports/analog/boards/max32650fthr/mpconfigboard.mk @@ -0,0 +1,31 @@ +# This file is part of the CircuitPython project: https://circuitpython.org +# +# SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +# SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc +# +# SPDX-License-Identifier: MIT + +MCU_SERIES=max32 +MCU_VARIANT=max32650 + +INTERNAL_FLASH_FILESYSTEM=1 +# FLASH: 0x10000000 to 0x10300000 (ARM) +# SRAM: 0x20000000 to 0x20100000 + +#### USB CONFIGURATION +# Use 0x0456 for Analog Devices, Inc.; 0B6A for Maxim +USB_VID=0x0456 +# USB_VID=0x0B6A +USB_PID=0x003C +USB_MANUFACTURER="Analog Devices, Inc." +USB_PRODUCT="MAX32650FTHR" + +# NOTE: MAX32 devices do not support IN/OUT pairs on the same EP +USB_NUM_ENDPOINT_PAIRS=12 +### + +# define UID len for memory safety (buffer gets passed as a raw ptr) +COMMON_HAL_MCU_PROCESSOR_UID_LENGTH=30 + +# NOTE: Not implementing external flash for now +# CFLAGS+=-DEXT_FLASH_MX25 diff --git a/ports/analog/boards/max32650fthr/pins.c b/ports/analog/boards/max32650fthr/pins.c new file mode 100644 index 00000000000..7bd14e5e97c --- /dev/null +++ b/ports/analog/boards/max32650fthr/pins.c @@ -0,0 +1,126 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + // P0 + { MP_ROM_QSTR(MP_QSTR_P0_0), MP_ROM_PTR(&pin_P0_00) }, + { MP_ROM_QSTR(MP_QSTR_P0_1), MP_ROM_PTR(&pin_P0_01) }, + { MP_ROM_QSTR(MP_QSTR_P0_2), MP_ROM_PTR(&pin_P0_02) }, + { MP_ROM_QSTR(MP_QSTR_P0_3), MP_ROM_PTR(&pin_P0_03) }, + { MP_ROM_QSTR(MP_QSTR_P0_4), MP_ROM_PTR(&pin_P0_04) }, + { MP_ROM_QSTR(MP_QSTR_P0_5), MP_ROM_PTR(&pin_P0_05) }, + { MP_ROM_QSTR(MP_QSTR_P0_6), MP_ROM_PTR(&pin_P0_06) }, + { MP_ROM_QSTR(MP_QSTR_P0_7), MP_ROM_PTR(&pin_P0_07) }, + { MP_ROM_QSTR(MP_QSTR_P0_8), MP_ROM_PTR(&pin_P0_08) }, + { MP_ROM_QSTR(MP_QSTR_P0_9), MP_ROM_PTR(&pin_P0_09) }, + { MP_ROM_QSTR(MP_QSTR_P0_10), MP_ROM_PTR(&pin_P0_10) }, + { MP_ROM_QSTR(MP_QSTR_P0_11), MP_ROM_PTR(&pin_P0_11) }, + { MP_ROM_QSTR(MP_QSTR_P0_12), MP_ROM_PTR(&pin_P0_12) }, + { MP_ROM_QSTR(MP_QSTR_P0_13), MP_ROM_PTR(&pin_P0_13) }, + { MP_ROM_QSTR(MP_QSTR_P0_14), MP_ROM_PTR(&pin_P0_14) }, + { MP_ROM_QSTR(MP_QSTR_P0_15), MP_ROM_PTR(&pin_P0_15) }, + { MP_ROM_QSTR(MP_QSTR_P0_16), MP_ROM_PTR(&pin_P0_16) }, + { MP_ROM_QSTR(MP_QSTR_P0_17), MP_ROM_PTR(&pin_P0_17) }, + { MP_ROM_QSTR(MP_QSTR_P0_18), MP_ROM_PTR(&pin_P0_18) }, + { MP_ROM_QSTR(MP_QSTR_P0_19), MP_ROM_PTR(&pin_P0_19) }, + { MP_ROM_QSTR(MP_QSTR_P0_20), MP_ROM_PTR(&pin_P0_20) }, + { MP_ROM_QSTR(MP_QSTR_P0_21), MP_ROM_PTR(&pin_P0_21) }, + { MP_ROM_QSTR(MP_QSTR_P0_22), MP_ROM_PTR(&pin_P0_22) }, + { MP_ROM_QSTR(MP_QSTR_P0_23), MP_ROM_PTR(&pin_P0_23) }, + { MP_ROM_QSTR(MP_QSTR_P0_24), MP_ROM_PTR(&pin_P0_24) }, + { MP_ROM_QSTR(MP_QSTR_P0_25), MP_ROM_PTR(&pin_P0_25) }, + { MP_ROM_QSTR(MP_QSTR_P0_26), MP_ROM_PTR(&pin_P0_26) }, + { MP_ROM_QSTR(MP_QSTR_P0_27), MP_ROM_PTR(&pin_P0_27) }, + { MP_ROM_QSTR(MP_QSTR_P0_28), MP_ROM_PTR(&pin_P0_28) }, + { MP_ROM_QSTR(MP_QSTR_P0_29), MP_ROM_PTR(&pin_P0_29) }, + { MP_ROM_QSTR(MP_QSTR_P0_30), MP_ROM_PTR(&pin_P0_30) }, + { MP_ROM_QSTR(MP_QSTR_P0_31), MP_ROM_PTR(&pin_P0_31) }, + // P1 + { MP_ROM_QSTR(MP_QSTR_P1_0), MP_ROM_PTR(&pin_P1_00) }, + { MP_ROM_QSTR(MP_QSTR_P1_1), MP_ROM_PTR(&pin_P1_01) }, + { MP_ROM_QSTR(MP_QSTR_P1_2), MP_ROM_PTR(&pin_P1_02) }, + { MP_ROM_QSTR(MP_QSTR_P1_3), MP_ROM_PTR(&pin_P1_03) }, + { MP_ROM_QSTR(MP_QSTR_P1_4), MP_ROM_PTR(&pin_P1_04) }, + { MP_ROM_QSTR(MP_QSTR_P1_5), MP_ROM_PTR(&pin_P1_05) }, + { MP_ROM_QSTR(MP_QSTR_P1_6), MP_ROM_PTR(&pin_P1_06) }, + { MP_ROM_QSTR(MP_QSTR_P1_7), MP_ROM_PTR(&pin_P1_07) }, + { MP_ROM_QSTR(MP_QSTR_P1_8), MP_ROM_PTR(&pin_P1_08) }, + { MP_ROM_QSTR(MP_QSTR_P1_9), MP_ROM_PTR(&pin_P1_09) }, + { MP_ROM_QSTR(MP_QSTR_P1_10), MP_ROM_PTR(&pin_P1_10) }, + { MP_ROM_QSTR(MP_QSTR_P1_11), MP_ROM_PTR(&pin_P1_11) }, + { MP_ROM_QSTR(MP_QSTR_P1_12), MP_ROM_PTR(&pin_P1_12) }, + { MP_ROM_QSTR(MP_QSTR_P1_13), MP_ROM_PTR(&pin_P1_13) }, + { MP_ROM_QSTR(MP_QSTR_P1_14), MP_ROM_PTR(&pin_P1_14) }, + { MP_ROM_QSTR(MP_QSTR_P1_15), MP_ROM_PTR(&pin_P1_15) }, + { MP_ROM_QSTR(MP_QSTR_P1_16), MP_ROM_PTR(&pin_P1_16) }, + { MP_ROM_QSTR(MP_QSTR_P1_17), MP_ROM_PTR(&pin_P1_17) }, + { MP_ROM_QSTR(MP_QSTR_P1_18), MP_ROM_PTR(&pin_P1_18) }, + { MP_ROM_QSTR(MP_QSTR_P1_19), MP_ROM_PTR(&pin_P1_19) }, + { MP_ROM_QSTR(MP_QSTR_P1_20), MP_ROM_PTR(&pin_P1_20) }, + { MP_ROM_QSTR(MP_QSTR_P1_21), MP_ROM_PTR(&pin_P1_21) }, + { MP_ROM_QSTR(MP_QSTR_P1_22), MP_ROM_PTR(&pin_P1_22) }, + { MP_ROM_QSTR(MP_QSTR_P1_23), MP_ROM_PTR(&pin_P1_23) }, + { MP_ROM_QSTR(MP_QSTR_P1_24), MP_ROM_PTR(&pin_P1_24) }, + { MP_ROM_QSTR(MP_QSTR_P1_25), MP_ROM_PTR(&pin_P1_25) }, + { MP_ROM_QSTR(MP_QSTR_P1_26), MP_ROM_PTR(&pin_P1_26) }, + { MP_ROM_QSTR(MP_QSTR_P1_27), MP_ROM_PTR(&pin_P1_27) }, + { MP_ROM_QSTR(MP_QSTR_P1_28), MP_ROM_PTR(&pin_P1_28) }, + { MP_ROM_QSTR(MP_QSTR_P1_29), MP_ROM_PTR(&pin_P1_29) }, + { MP_ROM_QSTR(MP_QSTR_P1_30), MP_ROM_PTR(&pin_P1_30) }, + { MP_ROM_QSTR(MP_QSTR_P1_31), MP_ROM_PTR(&pin_P1_31) }, + // P2 + { MP_ROM_QSTR(MP_QSTR_P2_0), MP_ROM_PTR(&pin_P2_00) }, + { MP_ROM_QSTR(MP_QSTR_P2_1), MP_ROM_PTR(&pin_P2_01) }, + { MP_ROM_QSTR(MP_QSTR_P2_2), MP_ROM_PTR(&pin_P2_02) }, + { MP_ROM_QSTR(MP_QSTR_P2_3), MP_ROM_PTR(&pin_P2_03) }, + { MP_ROM_QSTR(MP_QSTR_P2_4), MP_ROM_PTR(&pin_P2_04) }, + { MP_ROM_QSTR(MP_QSTR_P2_5), MP_ROM_PTR(&pin_P2_05) }, + { MP_ROM_QSTR(MP_QSTR_P2_6), MP_ROM_PTR(&pin_P2_06) }, + { MP_ROM_QSTR(MP_QSTR_P2_7), MP_ROM_PTR(&pin_P2_07) }, + { MP_ROM_QSTR(MP_QSTR_P2_8), MP_ROM_PTR(&pin_P2_08) }, + { MP_ROM_QSTR(MP_QSTR_P2_9), MP_ROM_PTR(&pin_P2_09) }, + { MP_ROM_QSTR(MP_QSTR_P2_10), MP_ROM_PTR(&pin_P2_10) }, + { MP_ROM_QSTR(MP_QSTR_P2_11), MP_ROM_PTR(&pin_P2_11) }, + { MP_ROM_QSTR(MP_QSTR_P2_12), MP_ROM_PTR(&pin_P2_12) }, + { MP_ROM_QSTR(MP_QSTR_P2_13), MP_ROM_PTR(&pin_P2_13) }, + { MP_ROM_QSTR(MP_QSTR_P2_14), MP_ROM_PTR(&pin_P2_14) }, + { MP_ROM_QSTR(MP_QSTR_P2_15), MP_ROM_PTR(&pin_P2_15) }, + { MP_ROM_QSTR(MP_QSTR_P2_16), MP_ROM_PTR(&pin_P2_16) }, + { MP_ROM_QSTR(MP_QSTR_P2_17), MP_ROM_PTR(&pin_P2_17) }, + { MP_ROM_QSTR(MP_QSTR_P2_18), MP_ROM_PTR(&pin_P2_18) }, + { MP_ROM_QSTR(MP_QSTR_P2_19), MP_ROM_PTR(&pin_P2_19) }, + { MP_ROM_QSTR(MP_QSTR_P2_20), MP_ROM_PTR(&pin_P2_20) }, + { MP_ROM_QSTR(MP_QSTR_P2_21), MP_ROM_PTR(&pin_P2_21) }, + { MP_ROM_QSTR(MP_QSTR_P2_22), MP_ROM_PTR(&pin_P2_22) }, + { MP_ROM_QSTR(MP_QSTR_P2_23), MP_ROM_PTR(&pin_P2_23) }, + { MP_ROM_QSTR(MP_QSTR_P2_24), MP_ROM_PTR(&pin_P2_24) }, + { MP_ROM_QSTR(MP_QSTR_P2_25), MP_ROM_PTR(&pin_P2_25) }, + { MP_ROM_QSTR(MP_QSTR_P2_26), MP_ROM_PTR(&pin_P2_26) }, + { MP_ROM_QSTR(MP_QSTR_P2_27), MP_ROM_PTR(&pin_P2_27) }, + { MP_ROM_QSTR(MP_QSTR_P2_28), MP_ROM_PTR(&pin_P2_28) }, + { MP_ROM_QSTR(MP_QSTR_P2_29), MP_ROM_PTR(&pin_P2_29) }, + { MP_ROM_QSTR(MP_QSTR_P2_30), MP_ROM_PTR(&pin_P2_30) }, + { MP_ROM_QSTR(MP_QSTR_P2_31), MP_ROM_PTR(&pin_P2_31) }, + // P3 + { MP_ROM_QSTR(MP_QSTR_P3_0), MP_ROM_PTR(&pin_P3_00) }, + { MP_ROM_QSTR(MP_QSTR_P3_1), MP_ROM_PTR(&pin_P3_01) }, + { MP_ROM_QSTR(MP_QSTR_P3_2), MP_ROM_PTR(&pin_P3_02) }, + { MP_ROM_QSTR(MP_QSTR_P3_3), MP_ROM_PTR(&pin_P3_03) }, + { MP_ROM_QSTR(MP_QSTR_P3_4), MP_ROM_PTR(&pin_P3_04) }, + { MP_ROM_QSTR(MP_QSTR_P3_5), MP_ROM_PTR(&pin_P3_05) }, + { MP_ROM_QSTR(MP_QSTR_P3_6), MP_ROM_PTR(&pin_P3_06) }, + { MP_ROM_QSTR(MP_QSTR_P3_7), MP_ROM_PTR(&pin_P3_07) }, + { MP_ROM_QSTR(MP_QSTR_P3_8), MP_ROM_PTR(&pin_P3_08) }, + { MP_ROM_QSTR(MP_QSTR_P3_9), MP_ROM_PTR(&pin_P3_09) }, + + /** @TODO: Silkscreen aliases */ + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/analog/boards/max32666fthr/README.md b/ports/analog/boards/max32666fthr/README.md new file mode 100644 index 00000000000..abdfb9cee36 --- /dev/null +++ b/ports/analog/boards/max32666fthr/README.md @@ -0,0 +1,33 @@ +# MAX32666FTHR + +[TODO] + +## Onboard connectors & peripherals + +[TODO] + +## Product Resources + +[TODO] + +### Building for this board + +To build for this board, ensure you are in the `ports/analog` directory and run the following command. Note that passing in the `-jN` flag, where N is the # of cores on your machine, can speed up compile times. + +``` +make BOARD=max32666fthr +``` + +### Flashing this board + +To flash the board, run the following command if using the MAX32625PICO: + +``` +make BOARD=max32666fthr flash-msdk +``` + +If using Segger JLink, please run the following command instead: + +``` +make BOARD=max32666fthr flash-jlink +``` diff --git a/ports/analog/boards/max32666fthr/board.c b/ports/analog/boards/max32666fthr/board.c new file mode 100644 index 00000000000..76c3e7f5591 --- /dev/null +++ b/ports/analog/boards/max32666fthr/board.c @@ -0,0 +1,32 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "supervisor/port.h" +#include "mpconfigboard.h" +#include "max32_port.h" + +/***** OPTIONAL BOARD-SPECIFIC FUNCTIONS from supervisor/board.h *****/ +// DEFAULT: Using the weak-defined supervisor/shared/board.c functions + +// Initializes board related state once on start up. +void board_init(void) { +} + +// Returns true if the user initiates safe mode in a board specific way. +// Also add BOARD_USER_SAFE_MODE in mpconfigboard.h to explain the board specific +// way. +// bool board_requests_safe_mode(void); + +// Reset the state of off MCU components such as neopixels. +// void reset_board(void); + +// Deinit the board. This should put the board in deep sleep durable, low power +// state. It should not prevent the user access method from working (such as +// disabling USB, BLE or flash) because CircuitPython may continue to run. +// void board_deinit(void); + +/*******************************************************************/ diff --git a/ports/analog/boards/max32666fthr/mpconfigboard.h b/ports/analog/boards/max32666fthr/mpconfigboard.h new file mode 100644 index 00000000000..d04b1ce6f8d --- /dev/null +++ b/ports/analog/boards/max32666fthr/mpconfigboard.h @@ -0,0 +1,40 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices Inc. +// +// SPDX-License-Identifier: MIT + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2016 Glenn Ruben Bakke +// SPDX-FileCopyrightText: Copyright (c) 2018 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "MAX32666FTHR" +#define MICROPY_HW_MCU_NAME "max32665" + +#define FLASH_SIZE (0x100000) // 1MiB +#define FLASH_PAGE_SIZE (0x4000) // 16384 byte pages (16 KiB) + +#define BOARD_HAS_CRYSTAL 1 +#define NUM_GPIO_PORTS 2 +#define CONSOLE_UART MXC_UART1 + +// #if INTERNAL_FLASH_FILESYSTEM +#define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_START_ADDR (0x100E0000) // for MAX32666 +#define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE (128 * 1024) // 128K + +#define MAX32_FLASH_SIZE 0x100000 // 1 MiB +#define INTERNAL_FLASH_FILESYSTEM_SIZE CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE +#define INTERNAL_FLASH_FILESYSTEM_START_ADDR 0x100E0000 // Load into the last MiB of code/data storage + +// #else +// #define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE (0) +// #endif + +#define MICROPY_HW_LED_STATUS (&pin_P0_31) diff --git a/ports/analog/boards/max32666fthr/mpconfigboard.mk b/ports/analog/boards/max32666fthr/mpconfigboard.mk new file mode 100644 index 00000000000..402e6dca42e --- /dev/null +++ b/ports/analog/boards/max32666fthr/mpconfigboard.mk @@ -0,0 +1,31 @@ +# This file is part of the CircuitPython project: https://circuitpython.org +# +# SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +# SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc +# +# SPDX-License-Identifier: MIT + +MCU_SERIES=max32 +MCU_VARIANT=max32665 + +INTERNAL_FLASH_FILESYSTEM=1 +# FLASH: 0x10000000 to 0x10100000 +# SRAM: 0x20000000 to 0x20100000 + +#### USB CONFIGURATION +# Use 0x0456 for Analog Devices, Inc.; 0B6A for Maxim +USB_VID=0x0456 +# USB_VID=0x0B6A +USB_PID=0x003C +USB_MANUFACTURER="Analog Devices, Inc." +USB_PRODUCT="MAX32666FTHR" + +# NOTE: MAX32 devices do not support IN/OUT pairs on the same EP +USB_NUM_ENDPOINT_PAIRS=12 +### + +# define UID len for memory safety (buffer gets passed as a raw ptr) +COMMON_HAL_MCU_PROCESSOR_UID_LENGTH=30 + +# NOTE: Not implementing external flash for now +# CFLAGS+=-DEXT_FLASH_MX25 diff --git a/ports/analog/boards/max32666fthr/pins.c b/ports/analog/boards/max32666fthr/pins.c new file mode 100644 index 00000000000..6e452b2d8ee --- /dev/null +++ b/ports/analog/boards/max32666fthr/pins.c @@ -0,0 +1,66 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + // P0 + { MP_ROM_QSTR(MP_QSTR_P0_0), MP_ROM_PTR(&pin_P0_00) }, + { MP_ROM_QSTR(MP_QSTR_P0_1), MP_ROM_PTR(&pin_P0_01) }, + { MP_ROM_QSTR(MP_QSTR_P0_2), MP_ROM_PTR(&pin_P0_02) }, + { MP_ROM_QSTR(MP_QSTR_P0_3), MP_ROM_PTR(&pin_P0_03) }, + { MP_ROM_QSTR(MP_QSTR_P0_4), MP_ROM_PTR(&pin_P0_04) }, + { MP_ROM_QSTR(MP_QSTR_P0_5), MP_ROM_PTR(&pin_P0_05) }, + { MP_ROM_QSTR(MP_QSTR_P0_6), MP_ROM_PTR(&pin_P0_06) }, + { MP_ROM_QSTR(MP_QSTR_P0_7), MP_ROM_PTR(&pin_P0_07) }, + { MP_ROM_QSTR(MP_QSTR_P0_8), MP_ROM_PTR(&pin_P0_08) }, + { MP_ROM_QSTR(MP_QSTR_P0_9), MP_ROM_PTR(&pin_P0_09) }, + { MP_ROM_QSTR(MP_QSTR_P0_10), MP_ROM_PTR(&pin_P0_10) }, + { MP_ROM_QSTR(MP_QSTR_P0_11), MP_ROM_PTR(&pin_P0_11) }, + { MP_ROM_QSTR(MP_QSTR_P0_12), MP_ROM_PTR(&pin_P0_12) }, + { MP_ROM_QSTR(MP_QSTR_P0_13), MP_ROM_PTR(&pin_P0_13) }, + { MP_ROM_QSTR(MP_QSTR_P0_14), MP_ROM_PTR(&pin_P0_14) }, + { MP_ROM_QSTR(MP_QSTR_P0_15), MP_ROM_PTR(&pin_P0_15) }, + { MP_ROM_QSTR(MP_QSTR_P0_16), MP_ROM_PTR(&pin_P0_16) }, + { MP_ROM_QSTR(MP_QSTR_P0_17), MP_ROM_PTR(&pin_P0_17) }, + { MP_ROM_QSTR(MP_QSTR_P0_18), MP_ROM_PTR(&pin_P0_18) }, + { MP_ROM_QSTR(MP_QSTR_P0_19), MP_ROM_PTR(&pin_P0_19) }, + { MP_ROM_QSTR(MP_QSTR_P0_20), MP_ROM_PTR(&pin_P0_20) }, + { MP_ROM_QSTR(MP_QSTR_P0_21), MP_ROM_PTR(&pin_P0_21) }, + { MP_ROM_QSTR(MP_QSTR_P0_22), MP_ROM_PTR(&pin_P0_22) }, + { MP_ROM_QSTR(MP_QSTR_P0_23), MP_ROM_PTR(&pin_P0_23) }, + { MP_ROM_QSTR(MP_QSTR_P0_24), MP_ROM_PTR(&pin_P0_24) }, + { MP_ROM_QSTR(MP_QSTR_P0_25), MP_ROM_PTR(&pin_P0_25) }, + { MP_ROM_QSTR(MP_QSTR_P0_26), MP_ROM_PTR(&pin_P0_26) }, + { MP_ROM_QSTR(MP_QSTR_P0_27), MP_ROM_PTR(&pin_P0_27) }, + { MP_ROM_QSTR(MP_QSTR_P0_28), MP_ROM_PTR(&pin_P0_28) }, + { MP_ROM_QSTR(MP_QSTR_P0_29), MP_ROM_PTR(&pin_P0_29) }, + { MP_ROM_QSTR(MP_QSTR_P0_30), MP_ROM_PTR(&pin_P0_30) }, + { MP_ROM_QSTR(MP_QSTR_P0_31), MP_ROM_PTR(&pin_P0_31) }, + // P1 + { MP_ROM_QSTR(MP_QSTR_P1_0), MP_ROM_PTR(&pin_P1_00) }, + { MP_ROM_QSTR(MP_QSTR_P1_1), MP_ROM_PTR(&pin_P1_01) }, + { MP_ROM_QSTR(MP_QSTR_P1_2), MP_ROM_PTR(&pin_P1_02) }, + { MP_ROM_QSTR(MP_QSTR_P1_3), MP_ROM_PTR(&pin_P1_03) }, + { MP_ROM_QSTR(MP_QSTR_P1_4), MP_ROM_PTR(&pin_P1_04) }, + { MP_ROM_QSTR(MP_QSTR_P1_5), MP_ROM_PTR(&pin_P1_05) }, + { MP_ROM_QSTR(MP_QSTR_P1_6), MP_ROM_PTR(&pin_P1_06) }, + { MP_ROM_QSTR(MP_QSTR_P1_7), MP_ROM_PTR(&pin_P1_07) }, + { MP_ROM_QSTR(MP_QSTR_P1_8), MP_ROM_PTR(&pin_P1_08) }, + { MP_ROM_QSTR(MP_QSTR_P1_9), MP_ROM_PTR(&pin_P1_09) }, + { MP_ROM_QSTR(MP_QSTR_P1_10), MP_ROM_PTR(&pin_P1_10) }, + { MP_ROM_QSTR(MP_QSTR_P1_11), MP_ROM_PTR(&pin_P1_11) }, + { MP_ROM_QSTR(MP_QSTR_P1_12), MP_ROM_PTR(&pin_P1_12) }, + { MP_ROM_QSTR(MP_QSTR_P1_13), MP_ROM_PTR(&pin_P1_13) }, + { MP_ROM_QSTR(MP_QSTR_P1_14), MP_ROM_PTR(&pin_P1_14) }, + { MP_ROM_QSTR(MP_QSTR_P1_15), MP_ROM_PTR(&pin_P1_15) }, + + /** @TODO: Silkscreen aliases */ + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); From 4a6e9b91da77b16f54a2c463518a922665fd392d Mon Sep 17 00:00:00 2001 From: Brandon Date: Mon, 5 Jan 2026 23:59:02 -0800 Subject: [PATCH 09/23] ports: analog: Add peripherals for MAX32650 & MAX32666 Signed-off-by: Brandon --- ports/analog/peripherals/max32650/gpios.c | 10 ++ ports/analog/peripherals/max32650/gpios.h | 15 +++ ports/analog/peripherals/max32650/max32_i2c.c | 35 +++++ ports/analog/peripherals/max32650/max32_i2c.h | 16 +++ ports/analog/peripherals/max32650/max32_spi.c | 44 +++++++ ports/analog/peripherals/max32650/max32_spi.h | 18 +++ .../analog/peripherals/max32650/max32_uart.c | 34 +++++ .../analog/peripherals/max32650/max32_uart.h | 16 +++ ports/analog/peripherals/max32650/pins.c | 120 ++++++++++++++++++ ports/analog/peripherals/max32650/pins.h | 117 +++++++++++++++++ ports/analog/peripherals/max32665/gpios.c | 10 ++ ports/analog/peripherals/max32665/gpios.h | 15 +++ ports/analog/peripherals/max32665/max32_i2c.c | 38 ++++++ ports/analog/peripherals/max32665/max32_i2c.h | 16 +++ ports/analog/peripherals/max32665/max32_spi.c | 45 +++++++ ports/analog/peripherals/max32665/max32_spi.h | 17 +++ .../analog/peripherals/max32665/max32_uart.c | 40 ++++++ .../analog/peripherals/max32665/max32_uart.h | 16 +++ ports/analog/peripherals/max32665/pins.c | 60 +++++++++ ports/analog/peripherals/max32665/pins.h | 57 +++++++++ 20 files changed, 739 insertions(+) create mode 100644 ports/analog/peripherals/max32650/gpios.c create mode 100644 ports/analog/peripherals/max32650/gpios.h create mode 100644 ports/analog/peripherals/max32650/max32_i2c.c create mode 100644 ports/analog/peripherals/max32650/max32_i2c.h create mode 100644 ports/analog/peripherals/max32650/max32_spi.c create mode 100644 ports/analog/peripherals/max32650/max32_spi.h create mode 100644 ports/analog/peripherals/max32650/max32_uart.c create mode 100644 ports/analog/peripherals/max32650/max32_uart.h create mode 100644 ports/analog/peripherals/max32650/pins.c create mode 100644 ports/analog/peripherals/max32650/pins.h create mode 100644 ports/analog/peripherals/max32665/gpios.c create mode 100644 ports/analog/peripherals/max32665/gpios.h create mode 100644 ports/analog/peripherals/max32665/max32_i2c.c create mode 100644 ports/analog/peripherals/max32665/max32_i2c.h create mode 100644 ports/analog/peripherals/max32665/max32_spi.c create mode 100644 ports/analog/peripherals/max32665/max32_spi.h create mode 100644 ports/analog/peripherals/max32665/max32_uart.c create mode 100644 ports/analog/peripherals/max32665/max32_uart.h create mode 100644 ports/analog/peripherals/max32665/pins.c create mode 100644 ports/analog/peripherals/max32665/pins.h diff --git a/ports/analog/peripherals/max32650/gpios.c b/ports/analog/peripherals/max32650/gpios.c new file mode 100644 index 00000000000..ba3e25a3c2d --- /dev/null +++ b/ports/analog/peripherals/max32650/gpios.c @@ -0,0 +1,10 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "gpios.h" + +volatile mxc_gpio_regs_t *gpio_ports[NUM_GPIO_PORTS] = +{MXC_GPIO0, MXC_GPIO1, MXC_GPIO2, MXC_GPIO3}; diff --git a/ports/analog/peripherals/max32650/gpios.h b/ports/analog/peripherals/max32650/gpios.h new file mode 100644 index 00000000000..65bac51e444 --- /dev/null +++ b/ports/analog/peripherals/max32650/gpios.h @@ -0,0 +1,15 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "py/mphal.h" + +// MSDK HAL includes +#include "gpio.h" +#include "gpio_regs.h" +#include "max32650.h" diff --git a/ports/analog/peripherals/max32650/max32_i2c.c b/ports/analog/peripherals/max32650/max32_i2c.c new file mode 100644 index 00000000000..00a247d88e9 --- /dev/null +++ b/ports/analog/peripherals/max32650/max32_i2c.c @@ -0,0 +1,35 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "peripherals/pins.h" + +#include "common-hal/busio/I2C.h" +#include "max32_i2c.h" +#include "max32650.h" + +#include "py/runtime.h" +#include "py/mperrno.h" + +const mxc_gpio_cfg_t i2c_maps[NUM_I2C] = { + // I2C0 + { MXC_GPIO2, (MXC_GPIO_PIN_7 | MXC_GPIO_PIN_8), MXC_GPIO_FUNC_ALT1, + MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + // I2C1 + { MXC_GPIO2, (MXC_GPIO_PIN_17 | MXC_GPIO_PIN_18), MXC_GPIO_FUNC_ALT1, + MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, +}; + +int pinsToI2c(const mcu_pin_obj_t *sda, const mcu_pin_obj_t *scl) { + for (int i = 0; i < NUM_I2C; i++) { + if ((i2c_maps[i].port == (MXC_GPIO_GET_GPIO(sda->port))) + && (i2c_maps[i].mask == ((sda->mask) | (scl->mask)))) { + return i; + } + } + + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_pins); + return -1; +} diff --git a/ports/analog/peripherals/max32650/max32_i2c.h b/ports/analog/peripherals/max32650/max32_i2c.h new file mode 100644 index 00000000000..3e554da5abc --- /dev/null +++ b/ports/analog/peripherals/max32650/max32_i2c.h @@ -0,0 +1,16 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "i2c_regs.h" +#include "mxc_sys.h" +#include "i2c.h" +#include "peripherals/pins.h" + +#define NUM_I2C 2 + +int pinsToI2c(const mcu_pin_obj_t *sda, const mcu_pin_obj_t *scl); diff --git a/ports/analog/peripherals/max32650/max32_spi.c b/ports/analog/peripherals/max32650/max32_spi.c new file mode 100644 index 00000000000..c8563dd8fe2 --- /dev/null +++ b/ports/analog/peripherals/max32650/max32_spi.c @@ -0,0 +1,44 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "peripherals/pins.h" + +#include "common-hal/busio/SPI.h" +#include "max32_spi.h" +#include "max32650.h" + +#include "py/runtime.h" +#include "py/mperrno.h" + +const mxc_gpio_cfg_t spi_maps[NUM_SPI] = { + // SPI0 + { MXC_GPIO2, (MXC_GPIO_PIN_27 | MXC_GPIO_PIN_28 | MXC_GPIO_PIN_29), + MXC_GPIO_FUNC_ALT2, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + // SPI1 + { MXC_GPIO1, (MXC_GPIO_PIN_26 | MXC_GPIO_PIN_28 | MXC_GPIO_PIN_29), + MXC_GPIO_FUNC_ALT1, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + // SPI2 + { MXC_GPIO2, (MXC_GPIO_PIN_2 | MXC_GPIO_PIN_3 | MXC_GPIO_PIN_4), + MXC_GPIO_FUNC_ALT1, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + // SPI3 + { MXC_GPIO0, (MXC_GPIO_PIN_16 | MXC_GPIO_PIN_20 | MXC_GPIO_PIN_21), + MXC_GPIO_FUNC_ALT1, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + // SPI4 + { MXC_GPIO1, (MXC_GPIO_PIN_1 | MXC_GPIO_PIN_2 | MXC_GPIO_PIN_3), + MXC_GPIO_FUNC_ALT1, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, +}; + +int pinsToSpi(const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, + const mcu_pin_obj_t *sck) { + for (int i = 0; i < NUM_SPI; i++) { + if ((spi_maps[i].port == (MXC_GPIO_GET_GPIO(mosi->port))) + && (spi_maps[i].mask == ((mosi->mask) | (miso->mask) | (sck->mask)))) { + return i; + } + } + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_pins); + return -1; +} diff --git a/ports/analog/peripherals/max32650/max32_spi.h b/ports/analog/peripherals/max32650/max32_spi.h new file mode 100644 index 00000000000..c4f6e8062f1 --- /dev/null +++ b/ports/analog/peripherals/max32650/max32_spi.h @@ -0,0 +1,18 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "spi_regs.h" +#include "mxc_sys.h" +#include "spi.h" +#include "peripherals/pins.h" + +// 3 APB SPI + 1 AHB QSPI +#define NUM_SPI 4 + +int pinsToSpi(const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, + const mcu_pin_obj_t *sck); diff --git a/ports/analog/peripherals/max32650/max32_uart.c b/ports/analog/peripherals/max32650/max32_uart.c new file mode 100644 index 00000000000..a6ebcc8033f --- /dev/null +++ b/ports/analog/peripherals/max32650/max32_uart.c @@ -0,0 +1,34 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "peripherals/pins.h" + +#include "common-hal/busio/UART.h" +#include "max32_uart.h" +#include "max32650.h" + +#include "py/runtime.h" +#include "py/mperrno.h" + +const mxc_gpio_cfg_t uart_maps[NUM_UARTS] = { + { MXC_GPIO2, (MXC_GPIO_PIN_11 | MXC_GPIO_PIN_12), MXC_GPIO_FUNC_ALT1, + MXC_GPIO_PAD_WEAK_PULL_UP, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + { MXC_GPIO2, (MXC_GPIO_PIN_14 | MXC_GPIO_PIN_16), MXC_GPIO_FUNC_ALT1, + MXC_GPIO_PAD_WEAK_PULL_UP, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + { MXC_GPIO1, (MXC_GPIO_PIN_9 | MXC_GPIO_PIN_10), MXC_GPIO_FUNC_ALT1, + MXC_GPIO_PAD_WEAK_PULL_UP, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, +}; + +int pinsToUart(const mcu_pin_obj_t *rx, const mcu_pin_obj_t *tx) { + for (int i = 0; i < NUM_UARTS; i++) { + if ((uart_maps[i].port == (MXC_GPIO_GET_GPIO(tx->port))) + && (uart_maps[i].mask == ((tx->mask) | (rx->mask)))) { + return i; + } + } + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_pins); + return -1; +} diff --git a/ports/analog/peripherals/max32650/max32_uart.h b/ports/analog/peripherals/max32650/max32_uart.h new file mode 100644 index 00000000000..c6a81925b5b --- /dev/null +++ b/ports/analog/peripherals/max32650/max32_uart.h @@ -0,0 +1,16 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "uart_regs.h" +#include "mxc_sys.h" +#include "uart.h" +#include "peripherals/pins.h" + +#define NUM_UARTS 3 + +int pinsToUart(const mcu_pin_obj_t *rx, const mcu_pin_obj_t *tx); diff --git a/ports/analog/peripherals/max32650/pins.c b/ports/analog/peripherals/max32650/pins.c new file mode 100644 index 00000000000..c420109311c --- /dev/null +++ b/ports/analog/peripherals/max32650/pins.c @@ -0,0 +1,120 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "py/obj.h" +#include "py/mphal.h" +#include "peripherals/pins.h" +#include "max32650.h" + +const mcu_pin_obj_t pin_P0_00 = PIN(0, 0); +const mcu_pin_obj_t pin_P0_01 = PIN(0, 1); +const mcu_pin_obj_t pin_P0_02 = PIN(0, 2); +const mcu_pin_obj_t pin_P0_03 = PIN(0, 3); +const mcu_pin_obj_t pin_P0_04 = PIN(0, 4); +const mcu_pin_obj_t pin_P0_05 = PIN(0, 5); +const mcu_pin_obj_t pin_P0_06 = PIN(0, 6); +const mcu_pin_obj_t pin_P0_07 = PIN(0, 7); +const mcu_pin_obj_t pin_P0_08 = PIN(0, 8); +const mcu_pin_obj_t pin_P0_09 = PIN(0, 9); +const mcu_pin_obj_t pin_P0_10 = PIN(0, 10); +const mcu_pin_obj_t pin_P0_11 = PIN(0, 11); +const mcu_pin_obj_t pin_P0_12 = PIN(0, 12); +const mcu_pin_obj_t pin_P0_13 = PIN(0, 13); +const mcu_pin_obj_t pin_P0_14 = PIN(0, 14); +const mcu_pin_obj_t pin_P0_15 = PIN(0, 15); +const mcu_pin_obj_t pin_P0_16 = PIN(0, 16); +const mcu_pin_obj_t pin_P0_17 = PIN(0, 17); +const mcu_pin_obj_t pin_P0_18 = PIN(0, 18); +const mcu_pin_obj_t pin_P0_19 = PIN(0, 19); +const mcu_pin_obj_t pin_P0_20 = PIN(0, 20); +const mcu_pin_obj_t pin_P0_21 = PIN(0, 21); +const mcu_pin_obj_t pin_P0_22 = PIN(0, 22); +const mcu_pin_obj_t pin_P0_23 = PIN(0, 23); +const mcu_pin_obj_t pin_P0_24 = PIN(0, 24); +const mcu_pin_obj_t pin_P0_25 = PIN(0, 25); +const mcu_pin_obj_t pin_P0_26 = PIN(0, 26); +const mcu_pin_obj_t pin_P0_27 = PIN(0, 27); +const mcu_pin_obj_t pin_P0_28 = PIN(0, 28); +const mcu_pin_obj_t pin_P0_29 = PIN(0, 29); +const mcu_pin_obj_t pin_P0_30 = PIN(0, 30); +const mcu_pin_obj_t pin_P0_31 = PIN(0, 31); + +const mcu_pin_obj_t pin_P1_00 = PIN(1, 0); +const mcu_pin_obj_t pin_P1_01 = PIN(1, 1); +const mcu_pin_obj_t pin_P1_02 = PIN(1, 2); +const mcu_pin_obj_t pin_P1_03 = PIN(1, 3); +const mcu_pin_obj_t pin_P1_04 = PIN(1, 4); +const mcu_pin_obj_t pin_P1_05 = PIN(1, 5); +const mcu_pin_obj_t pin_P1_06 = PIN(1, 6); +const mcu_pin_obj_t pin_P1_07 = PIN(1, 7); +const mcu_pin_obj_t pin_P1_08 = PIN(1, 8); +const mcu_pin_obj_t pin_P1_09 = PIN(1, 9); +const mcu_pin_obj_t pin_P1_10 = PIN(1, 10); +const mcu_pin_obj_t pin_P1_11 = PIN(1, 11); +const mcu_pin_obj_t pin_P1_12 = PIN(1, 12); +const mcu_pin_obj_t pin_P1_13 = PIN(1, 13); +const mcu_pin_obj_t pin_P1_14 = PIN(1, 14); +const mcu_pin_obj_t pin_P1_15 = PIN(1, 15); +const mcu_pin_obj_t pin_P1_16 = PIN(1, 16); +const mcu_pin_obj_t pin_P1_17 = PIN(1, 17); +const mcu_pin_obj_t pin_P1_18 = PIN(1, 18); +const mcu_pin_obj_t pin_P1_19 = PIN(1, 19); +const mcu_pin_obj_t pin_P1_20 = PIN(1, 20); +const mcu_pin_obj_t pin_P1_21 = PIN(1, 21); +const mcu_pin_obj_t pin_P1_22 = PIN(1, 22); +const mcu_pin_obj_t pin_P1_23 = PIN(1, 23); +const mcu_pin_obj_t pin_P1_24 = PIN(1, 24); +const mcu_pin_obj_t pin_P1_25 = PIN(1, 25); +const mcu_pin_obj_t pin_P1_26 = PIN(1, 26); +const mcu_pin_obj_t pin_P1_27 = PIN(1, 27); +const mcu_pin_obj_t pin_P1_28 = PIN(1, 28); +const mcu_pin_obj_t pin_P1_29 = PIN(1, 29); +const mcu_pin_obj_t pin_P1_30 = PIN(1, 30); +const mcu_pin_obj_t pin_P1_31 = PIN(1, 31); + +const mcu_pin_obj_t pin_P2_00 = PIN(2, 0); +const mcu_pin_obj_t pin_P2_01 = PIN(2, 1); +const mcu_pin_obj_t pin_P2_02 = PIN(2, 2); +const mcu_pin_obj_t pin_P2_03 = PIN(2, 3); +const mcu_pin_obj_t pin_P2_04 = PIN(2, 4); +const mcu_pin_obj_t pin_P2_05 = PIN(2, 5); +const mcu_pin_obj_t pin_P2_06 = PIN(2, 6); +const mcu_pin_obj_t pin_P2_07 = PIN(2, 7); +const mcu_pin_obj_t pin_P2_08 = PIN(2, 8); +const mcu_pin_obj_t pin_P2_09 = PIN(2, 9); +const mcu_pin_obj_t pin_P2_10 = PIN(2, 10); +const mcu_pin_obj_t pin_P2_11 = PIN(2, 11); +const mcu_pin_obj_t pin_P2_12 = PIN(2, 12); +const mcu_pin_obj_t pin_P2_13 = PIN(2, 13); +const mcu_pin_obj_t pin_P2_14 = PIN(2, 14); +const mcu_pin_obj_t pin_P2_15 = PIN(2, 15); +const mcu_pin_obj_t pin_P2_16 = PIN(2, 16); +const mcu_pin_obj_t pin_P2_17 = PIN(2, 17); +const mcu_pin_obj_t pin_P2_18 = PIN(2, 18); +const mcu_pin_obj_t pin_P2_19 = PIN(2, 19); +const mcu_pin_obj_t pin_P2_20 = PIN(2, 20); +const mcu_pin_obj_t pin_P2_21 = PIN(2, 21); +const mcu_pin_obj_t pin_P2_22 = PIN(2, 22); +const mcu_pin_obj_t pin_P2_23 = PIN(2, 23); +const mcu_pin_obj_t pin_P2_24 = PIN(2, 24); +const mcu_pin_obj_t pin_P2_25 = PIN(2, 25); +const mcu_pin_obj_t pin_P2_26 = PIN(2, 26); +const mcu_pin_obj_t pin_P2_27 = PIN(2, 27); +const mcu_pin_obj_t pin_P2_28 = PIN(2, 28); +const mcu_pin_obj_t pin_P2_29 = PIN(2, 29); +const mcu_pin_obj_t pin_P2_30 = PIN(2, 30); +const mcu_pin_obj_t pin_P2_31 = PIN(2, 31); + +const mcu_pin_obj_t pin_P3_00 = PIN(3, 0); +const mcu_pin_obj_t pin_P3_01 = PIN(3, 1); +const mcu_pin_obj_t pin_P3_02 = PIN(3, 2); +const mcu_pin_obj_t pin_P3_03 = PIN(3, 3); +const mcu_pin_obj_t pin_P3_04 = PIN(3, 4); +const mcu_pin_obj_t pin_P3_05 = PIN(3, 5); +const mcu_pin_obj_t pin_P3_06 = PIN(3, 6); +const mcu_pin_obj_t pin_P3_07 = PIN(3, 7); +const mcu_pin_obj_t pin_P3_08 = PIN(3, 8); +const mcu_pin_obj_t pin_P3_09 = PIN(3, 9); diff --git a/ports/analog/peripherals/max32650/pins.h b/ports/analog/peripherals/max32650/pins.h new file mode 100644 index 00000000000..2a41707844e --- /dev/null +++ b/ports/analog/peripherals/max32650/pins.h @@ -0,0 +1,117 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#pragma once + +extern const mcu_pin_obj_t pin_P0_00; +extern const mcu_pin_obj_t pin_P0_01; +extern const mcu_pin_obj_t pin_P0_02; +extern const mcu_pin_obj_t pin_P0_03; +extern const mcu_pin_obj_t pin_P0_04; +extern const mcu_pin_obj_t pin_P0_05; +extern const mcu_pin_obj_t pin_P0_06; +extern const mcu_pin_obj_t pin_P0_07; +extern const mcu_pin_obj_t pin_P0_08; +extern const mcu_pin_obj_t pin_P0_09; +extern const mcu_pin_obj_t pin_P0_10; +extern const mcu_pin_obj_t pin_P0_11; +extern const mcu_pin_obj_t pin_P0_12; +extern const mcu_pin_obj_t pin_P0_13; +extern const mcu_pin_obj_t pin_P0_14; +extern const mcu_pin_obj_t pin_P0_15; +extern const mcu_pin_obj_t pin_P0_16; +extern const mcu_pin_obj_t pin_P0_17; +extern const mcu_pin_obj_t pin_P0_18; +extern const mcu_pin_obj_t pin_P0_19; +extern const mcu_pin_obj_t pin_P0_20; +extern const mcu_pin_obj_t pin_P0_21; +extern const mcu_pin_obj_t pin_P0_22; +extern const mcu_pin_obj_t pin_P0_23; +extern const mcu_pin_obj_t pin_P0_24; +extern const mcu_pin_obj_t pin_P0_25; +extern const mcu_pin_obj_t pin_P0_26; +extern const mcu_pin_obj_t pin_P0_27; +extern const mcu_pin_obj_t pin_P0_28; +extern const mcu_pin_obj_t pin_P0_29; +extern const mcu_pin_obj_t pin_P0_30; +extern const mcu_pin_obj_t pin_P0_31; + +extern const mcu_pin_obj_t pin_P1_00; +extern const mcu_pin_obj_t pin_P1_01; +extern const mcu_pin_obj_t pin_P1_02; +extern const mcu_pin_obj_t pin_P1_03; +extern const mcu_pin_obj_t pin_P1_04; +extern const mcu_pin_obj_t pin_P1_05; +extern const mcu_pin_obj_t pin_P1_06; +extern const mcu_pin_obj_t pin_P1_07; +extern const mcu_pin_obj_t pin_P1_08; +extern const mcu_pin_obj_t pin_P1_09; +extern const mcu_pin_obj_t pin_P1_10; +extern const mcu_pin_obj_t pin_P1_11; +extern const mcu_pin_obj_t pin_P1_12; +extern const mcu_pin_obj_t pin_P1_13; +extern const mcu_pin_obj_t pin_P1_14; +extern const mcu_pin_obj_t pin_P1_15; +extern const mcu_pin_obj_t pin_P1_16; +extern const mcu_pin_obj_t pin_P1_17; +extern const mcu_pin_obj_t pin_P1_18; +extern const mcu_pin_obj_t pin_P1_19; +extern const mcu_pin_obj_t pin_P1_20; +extern const mcu_pin_obj_t pin_P1_21; +extern const mcu_pin_obj_t pin_P1_22; +extern const mcu_pin_obj_t pin_P1_23; +extern const mcu_pin_obj_t pin_P1_24; +extern const mcu_pin_obj_t pin_P1_25; +extern const mcu_pin_obj_t pin_P1_26; +extern const mcu_pin_obj_t pin_P1_27; +extern const mcu_pin_obj_t pin_P1_28; +extern const mcu_pin_obj_t pin_P1_29; +extern const mcu_pin_obj_t pin_P1_30; +extern const mcu_pin_obj_t pin_P1_31; + +extern const mcu_pin_obj_t pin_P2_00; +extern const mcu_pin_obj_t pin_P2_01; +extern const mcu_pin_obj_t pin_P2_02; +extern const mcu_pin_obj_t pin_P2_03; +extern const mcu_pin_obj_t pin_P2_04; +extern const mcu_pin_obj_t pin_P2_05; +extern const mcu_pin_obj_t pin_P2_06; +extern const mcu_pin_obj_t pin_P2_07; +extern const mcu_pin_obj_t pin_P2_08; +extern const mcu_pin_obj_t pin_P2_09; +extern const mcu_pin_obj_t pin_P2_10; +extern const mcu_pin_obj_t pin_P2_11; +extern const mcu_pin_obj_t pin_P2_12; +extern const mcu_pin_obj_t pin_P2_13; +extern const mcu_pin_obj_t pin_P2_14; +extern const mcu_pin_obj_t pin_P2_15; +extern const mcu_pin_obj_t pin_P2_16; +extern const mcu_pin_obj_t pin_P2_17; +extern const mcu_pin_obj_t pin_P2_18; +extern const mcu_pin_obj_t pin_P2_19; +extern const mcu_pin_obj_t pin_P2_20; +extern const mcu_pin_obj_t pin_P2_21; +extern const mcu_pin_obj_t pin_P2_22; +extern const mcu_pin_obj_t pin_P2_23; +extern const mcu_pin_obj_t pin_P2_24; +extern const mcu_pin_obj_t pin_P2_25; +extern const mcu_pin_obj_t pin_P2_26; +extern const mcu_pin_obj_t pin_P2_27; +extern const mcu_pin_obj_t pin_P2_28; +extern const mcu_pin_obj_t pin_P2_29; +extern const mcu_pin_obj_t pin_P2_30; +extern const mcu_pin_obj_t pin_P2_31; + +extern const mcu_pin_obj_t pin_P3_00; +extern const mcu_pin_obj_t pin_P3_01; +extern const mcu_pin_obj_t pin_P3_02; +extern const mcu_pin_obj_t pin_P3_03; +extern const mcu_pin_obj_t pin_P3_04; +extern const mcu_pin_obj_t pin_P3_05; +extern const mcu_pin_obj_t pin_P3_06; +extern const mcu_pin_obj_t pin_P3_07; +extern const mcu_pin_obj_t pin_P3_08; +extern const mcu_pin_obj_t pin_P3_09; diff --git a/ports/analog/peripherals/max32665/gpios.c b/ports/analog/peripherals/max32665/gpios.c new file mode 100644 index 00000000000..387c438e851 --- /dev/null +++ b/ports/analog/peripherals/max32665/gpios.c @@ -0,0 +1,10 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "gpios.h" + +volatile mxc_gpio_regs_t *gpio_ports[NUM_GPIO_PORTS] = +{MXC_GPIO0, MXC_GPIO1}; diff --git a/ports/analog/peripherals/max32665/gpios.h b/ports/analog/peripherals/max32665/gpios.h new file mode 100644 index 00000000000..30bd32f1407 --- /dev/null +++ b/ports/analog/peripherals/max32665/gpios.h @@ -0,0 +1,15 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "py/mphal.h" + +// MSDK HAL includes +#include "gpio.h" +#include "gpio_regs.h" +#include "max32665.h" diff --git a/ports/analog/peripherals/max32665/max32_i2c.c b/ports/analog/peripherals/max32665/max32_i2c.c new file mode 100644 index 00000000000..3fd4380cddd --- /dev/null +++ b/ports/analog/peripherals/max32665/max32_i2c.c @@ -0,0 +1,38 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "peripherals/pins.h" + +#include "common-hal/busio/I2C.h" +#include "max32_i2c.h" +#include "max32665.h" + +#include "py/runtime.h" +#include "py/mperrno.h" + +const mxc_gpio_cfg_t i2c_maps[NUM_I2C] = { + // I2C0 + { MXC_GPIO0, (MXC_GPIO_PIN_6 | MXC_GPIO_PIN_7), MXC_GPIO_FUNC_ALT1, + MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + // I2C1 + { MXC_GPIO0, (MXC_GPIO_PIN_14 | MXC_GPIO_PIN_15), MXC_GPIO_FUNC_ALT1, + MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + // I2C2 + { MXC_GPIO1, (MXC_GPIO_PIN_14 | MXC_GPIO_PIN_15), MXC_GPIO_FUNC_ALT1, + MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, +}; + +int pinsToI2c(const mcu_pin_obj_t *sda, const mcu_pin_obj_t *scl) { + for (int i = 0; i < NUM_I2C; i++) { + if ((i2c_maps[i].port == (MXC_GPIO_GET_GPIO(sda->port))) + && (i2c_maps[i].mask == ((sda->mask) | (scl->mask)))) { + return i; + } + } + + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_pins); + return -1; +} diff --git a/ports/analog/peripherals/max32665/max32_i2c.h b/ports/analog/peripherals/max32665/max32_i2c.h new file mode 100644 index 00000000000..b64cfd308dc --- /dev/null +++ b/ports/analog/peripherals/max32665/max32_i2c.h @@ -0,0 +1,16 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "i2c_regs.h" +#include "mxc_sys.h" +#include "i2c.h" +#include "peripherals/pins.h" + +#define NUM_I2C 3 + +int pinsToI2c(const mcu_pin_obj_t *sda, const mcu_pin_obj_t *scl); diff --git a/ports/analog/peripherals/max32665/max32_spi.c b/ports/analog/peripherals/max32665/max32_spi.c new file mode 100644 index 00000000000..2a97768bdc5 --- /dev/null +++ b/ports/analog/peripherals/max32665/max32_spi.c @@ -0,0 +1,45 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "peripherals/pins.h" + +#include "common-hal/busio/SPI.h" +#include "max32_spi.h" +#include "max32665.h" + +#include "py/runtime.h" +#include "py/mperrno.h" + +// Assuming the use of MAP_A in MSDK, since all documentation +// states the GPIO maps are the same + +const mxc_gpio_cfg_t spi_maps[NUM_SPI] = { + // SPI0A + { MXC_GPIO1, + (MXC_GPIO_PIN_9 | MXC_GPIO_PIN_10 | MXC_GPIO_PIN_11, MXC_GPIO_PIN_12, MXC_GPIO_PIN_13), + MXC_GPIO_FUNC_ALT1, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + // SPI1 + { MXC_GPIO0, + (MXC_GPIO_PIN_17 | MXC_GPIO_PIN_18 | MXC_GPIO_PIN_19, MXC_GPIO_PIN_20, MXC_GPIO_PIN_21), + MXC_GPIO_FUNC_ALT2, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + // SPI2 + { MXC_GPIO0, + (MXC_GPIO_PIN_25 | MXC_GPIO_PIN_26 | MXC_GPIO_PIN_27 | MXC_GPIO_PIN_28 | MXC_GPIO_PIN_29), + MXC_GPIO_FUNC_ALT2, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, +}; + + +int pinsToSpi(const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, + const mcu_pin_obj_t *sck) { + for (int i = 0; i < NUM_SPI; i++) { + if ((spi_maps[i].port == (MXC_GPIO_GET_GPIO(mosi->port))) + && (spi_maps[i].mask == ((mosi->mask) | (miso->mask) | (sck->mask)))) { + return i; + } + } + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_pins); + return -1; +} diff --git a/ports/analog/peripherals/max32665/max32_spi.h b/ports/analog/peripherals/max32665/max32_spi.h new file mode 100644 index 00000000000..54e51a1d6a0 --- /dev/null +++ b/ports/analog/peripherals/max32665/max32_spi.h @@ -0,0 +1,17 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "spi_regs.h" +#include "mxc_sys.h" +#include "spi.h" +#include "peripherals/pins.h" + +#define NUM_SPI 3 + +int pinsToSpi(const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, + const mcu_pin_obj_t *sck); diff --git a/ports/analog/peripherals/max32665/max32_uart.c b/ports/analog/peripherals/max32665/max32_uart.c new file mode 100644 index 00000000000..b89b6405811 --- /dev/null +++ b/ports/analog/peripherals/max32665/max32_uart.c @@ -0,0 +1,40 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "peripherals/pins.h" + +#include "common-hal/busio/UART.h" +#include "max32_uart.h" +#include "max32665.h" + +#include "py/runtime.h" +#include "py/mperrno.h" + +// Assuming the use of MAP_A in MSDK, since all documentation +// states the GPIO maps are the same + +const mxc_gpio_cfg_t uart_maps[NUM_UARTS] = { + // UART 0A + { MXC_GPIO0, (MXC_GPIO_PIN_9 | MXC_GPIO_PIN_10), MXC_GPIO_FUNC_ALT3, + MXC_GPIO_PAD_WEAK_PULL_UP, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + // UART 1A + { MXC_GPIO0, (MXC_GPIO_PIN_20 | MXC_GPIO_PIN_21), MXC_GPIO_FUNC_ALT3, + MXC_GPIO_PAD_WEAK_PULL_UP, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + // UART 2A + { MXC_GPIO0, (MXC_GPIO_PIN_1 | MXC_GPIO_PIN_2), MXC_GPIO_FUNC_ALT3, + MXC_GPIO_PAD_WEAK_PULL_UP, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, +}; + +int pinsToUart(const mcu_pin_obj_t *rx, const mcu_pin_obj_t *tx) { + for (int i = 0; i < NUM_UARTS; i++) { + if ((uart_maps[i].port == (MXC_GPIO_GET_GPIO(tx->port))) + && (uart_maps[i].mask == ((tx->mask) | (rx->mask)))) { + return i; + } + } + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_pins); + return -1; +} diff --git a/ports/analog/peripherals/max32665/max32_uart.h b/ports/analog/peripherals/max32665/max32_uart.h new file mode 100644 index 00000000000..c6a81925b5b --- /dev/null +++ b/ports/analog/peripherals/max32665/max32_uart.h @@ -0,0 +1,16 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "uart_regs.h" +#include "mxc_sys.h" +#include "uart.h" +#include "peripherals/pins.h" + +#define NUM_UARTS 3 + +int pinsToUart(const mcu_pin_obj_t *rx, const mcu_pin_obj_t *tx); diff --git a/ports/analog/peripherals/max32665/pins.c b/ports/analog/peripherals/max32665/pins.c new file mode 100644 index 00000000000..0024c56973b --- /dev/null +++ b/ports/analog/peripherals/max32665/pins.c @@ -0,0 +1,60 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "py/obj.h" +#include "py/mphal.h" +#include "peripherals/pins.h" +#include "max32665.h" + +const mcu_pin_obj_t pin_P0_00 = PIN(0, 0); +const mcu_pin_obj_t pin_P0_01 = PIN(0, 1); +const mcu_pin_obj_t pin_P0_02 = PIN(0, 2); +const mcu_pin_obj_t pin_P0_03 = PIN(0, 3); +const mcu_pin_obj_t pin_P0_04 = PIN(0, 4); +const mcu_pin_obj_t pin_P0_05 = PIN(0, 5); +const mcu_pin_obj_t pin_P0_06 = PIN(0, 6); +const mcu_pin_obj_t pin_P0_07 = PIN(0, 7); +const mcu_pin_obj_t pin_P0_08 = PIN(0, 8); +const mcu_pin_obj_t pin_P0_09 = PIN(0, 9); +const mcu_pin_obj_t pin_P0_10 = PIN(0, 10); +const mcu_pin_obj_t pin_P0_11 = PIN(0, 11); +const mcu_pin_obj_t pin_P0_12 = PIN(0, 12); +const mcu_pin_obj_t pin_P0_13 = PIN(0, 13); +const mcu_pin_obj_t pin_P0_14 = PIN(0, 14); +const mcu_pin_obj_t pin_P0_15 = PIN(0, 15); +const mcu_pin_obj_t pin_P0_16 = PIN(0, 16); +const mcu_pin_obj_t pin_P0_17 = PIN(0, 17); +const mcu_pin_obj_t pin_P0_18 = PIN(0, 18); +const mcu_pin_obj_t pin_P0_19 = PIN(0, 19); +const mcu_pin_obj_t pin_P0_20 = PIN(0, 20); +const mcu_pin_obj_t pin_P0_21 = PIN(0, 21); +const mcu_pin_obj_t pin_P0_22 = PIN(0, 22); +const mcu_pin_obj_t pin_P0_23 = PIN(0, 23); +const mcu_pin_obj_t pin_P0_24 = PIN(0, 24); +const mcu_pin_obj_t pin_P0_25 = PIN(0, 25); +const mcu_pin_obj_t pin_P0_26 = PIN(0, 26); +const mcu_pin_obj_t pin_P0_27 = PIN(0, 27); +const mcu_pin_obj_t pin_P0_28 = PIN(0, 28); +const mcu_pin_obj_t pin_P0_29 = PIN(0, 29); +const mcu_pin_obj_t pin_P0_30 = PIN(0, 30); +const mcu_pin_obj_t pin_P0_31 = PIN(0, 31); + +const mcu_pin_obj_t pin_P1_00 = PIN(1, 0); +const mcu_pin_obj_t pin_P1_01 = PIN(1, 1); +const mcu_pin_obj_t pin_P1_02 = PIN(1, 2); +const mcu_pin_obj_t pin_P1_03 = PIN(1, 3); +const mcu_pin_obj_t pin_P1_04 = PIN(1, 4); +const mcu_pin_obj_t pin_P1_05 = PIN(1, 5); +const mcu_pin_obj_t pin_P1_06 = PIN(1, 6); +const mcu_pin_obj_t pin_P1_07 = PIN(1, 7); +const mcu_pin_obj_t pin_P1_08 = PIN(1, 8); +const mcu_pin_obj_t pin_P1_09 = PIN(1, 9); +const mcu_pin_obj_t pin_P1_10 = PIN(1, 10); +const mcu_pin_obj_t pin_P1_11 = PIN(1, 11); +const mcu_pin_obj_t pin_P1_12 = PIN(1, 12); +const mcu_pin_obj_t pin_P1_13 = PIN(1, 13); +const mcu_pin_obj_t pin_P1_14 = PIN(1, 14); +const mcu_pin_obj_t pin_P1_15 = PIN(1, 15); diff --git a/ports/analog/peripherals/max32665/pins.h b/ports/analog/peripherals/max32665/pins.h new file mode 100644 index 00000000000..b3f8727c241 --- /dev/null +++ b/ports/analog/peripherals/max32665/pins.h @@ -0,0 +1,57 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#pragma once + +extern const mcu_pin_obj_t pin_P0_00; +extern const mcu_pin_obj_t pin_P0_01; +extern const mcu_pin_obj_t pin_P0_02; +extern const mcu_pin_obj_t pin_P0_03; +extern const mcu_pin_obj_t pin_P0_04; +extern const mcu_pin_obj_t pin_P0_05; +extern const mcu_pin_obj_t pin_P0_06; +extern const mcu_pin_obj_t pin_P0_07; +extern const mcu_pin_obj_t pin_P0_08; +extern const mcu_pin_obj_t pin_P0_09; +extern const mcu_pin_obj_t pin_P0_10; +extern const mcu_pin_obj_t pin_P0_11; +extern const mcu_pin_obj_t pin_P0_12; +extern const mcu_pin_obj_t pin_P0_13; +extern const mcu_pin_obj_t pin_P0_14; +extern const mcu_pin_obj_t pin_P0_15; +extern const mcu_pin_obj_t pin_P0_16; +extern const mcu_pin_obj_t pin_P0_17; +extern const mcu_pin_obj_t pin_P0_18; +extern const mcu_pin_obj_t pin_P0_19; +extern const mcu_pin_obj_t pin_P0_20; +extern const mcu_pin_obj_t pin_P0_21; +extern const mcu_pin_obj_t pin_P0_22; +extern const mcu_pin_obj_t pin_P0_23; +extern const mcu_pin_obj_t pin_P0_24; +extern const mcu_pin_obj_t pin_P0_25; +extern const mcu_pin_obj_t pin_P0_26; +extern const mcu_pin_obj_t pin_P0_27; +extern const mcu_pin_obj_t pin_P0_28; +extern const mcu_pin_obj_t pin_P0_29; +extern const mcu_pin_obj_t pin_P0_30; +extern const mcu_pin_obj_t pin_P0_31; + +extern const mcu_pin_obj_t pin_P1_00; +extern const mcu_pin_obj_t pin_P1_01; +extern const mcu_pin_obj_t pin_P1_02; +extern const mcu_pin_obj_t pin_P1_03; +extern const mcu_pin_obj_t pin_P1_04; +extern const mcu_pin_obj_t pin_P1_05; +extern const mcu_pin_obj_t pin_P1_06; +extern const mcu_pin_obj_t pin_P1_07; +extern const mcu_pin_obj_t pin_P1_08; +extern const mcu_pin_obj_t pin_P1_09; +extern const mcu_pin_obj_t pin_P1_10; +extern const mcu_pin_obj_t pin_P1_11; +extern const mcu_pin_obj_t pin_P1_12; +extern const mcu_pin_obj_t pin_P1_13; +extern const mcu_pin_obj_t pin_P1_14; +extern const mcu_pin_obj_t pin_P1_15; From 2d5eefa61e16f21410c0358e11c766fdbd6b46c3 Mon Sep 17 00:00:00 2001 From: Brandon-Hurst Date: Sat, 17 Jan 2026 16:55:34 -0800 Subject: [PATCH 10/23] ports: analog: Refactor port Makefile Cleanup and re-organize port-level Makefile. - Eliminate redundant include / source additions - Unify comment style and create logical sections - Inlude MSDK peripheral makefiles for each target - Mostly unify separate INC and SRC_C blocks - Refactor CFLAGs ordering - Add "pristine" build target for convenience - Reorganize build & flash rules --- ports/analog/Makefile | 273 ++++++++++++++++++------------------------ 1 file changed, 118 insertions(+), 155 deletions(-) diff --git a/ports/analog/Makefile b/ports/analog/Makefile index d37d2c2bf76..cd6a77bc5ae 100644 --- a/ports/analog/Makefile +++ b/ports/analog/Makefile @@ -13,6 +13,15 @@ CROSS_COMPILE = arm-none-eabi- # along with numerous other shared environment makefiles. include ../../py/circuitpy_mkenv.mk +################################################################################ +# DEFINITIONS +################################################################################ + +COMPILER ?= GCC +ifneq ($(COMPILER), GCC) +$(error ERR: Only the GCC compiler is supported.) +endif + # MCU_SERIES e.g. "max32" # MCU_VARIANT e.g. "max32690" # defined in mpconfigboard.mk @@ -21,32 +30,34 @@ MCU_SERIES_UPPER := $(shell echo $(MCU_SERIES) | tr '[:lower:]' '[:upper:]') MCU_VARIANT_LOWER := $(shell echo $(MCU_VARIANT) | tr '[:upper:]' '[:lower:]') MCU_VARIANT_UPPER := $(shell echo $(MCU_VARIANT) | tr '[:lower:]' '[:upper:]') -# ******************************************************************************* -#### MSDK INCLUDES #### # Necessary for msdk makefiles TARGET := $(MCU_VARIANT_UPPER) TARGET_UC := $(MCU_VARIANT_UPPER) TARGET_LC := $(MCU_VARIANT_LOWER) -MSDK_ROOT = ./msdk -MSDK_LIBS = $(MSDK_ROOT)/Libraries -CMSIS_ROOT = $(MSDK_LIBS)/CMSIS -ADI_PERIPH = $(MSDK_ROOT)/Libraries/PeriphDrivers -ADI_MISC_DRIVERS_DIR ?= $(MSDK_LIBS)/MiscDrivers -ADI_BOARD_DIR = $(MSDK_LIBS)/Boards/$(MCU_VARIANT_UPPER)/$(BOARD) - -# Set die type +# Define max32 die type for PeriphDriver Includes +# default to me18 for max32690 +# more info: +# https://analogdevicesinc.github.io/msdk//USERGUIDE/#die-types-to-part-numbers ifeq ($(MCU_VARIANT_LOWER),max32690) DIE_TYPE=me18 else ifeq ($(MCU_VARIANT_LOWER),max32650) DIE_TYPE=me10 else ifeq ($(MCU_VARIANT_LOWER),max32665) DIE_TYPE=me14 -else +else DIE_TYPE=me18 endif -# For debugging the build +# Helpful directory paths +MSDK_ROOT = ./msdk +MSDK_LIBS = $(MSDK_ROOT)/Libraries +CMSIS_ROOT = $(MSDK_LIBS)/CMSIS +ADI_PERIPH = $(MSDK_ROOT)/Libraries/PeriphDrivers +ADI_MISC_DRIVERS_DIR ?= $(MSDK_LIBS)/MiscDrivers +ADI_BOARD_DIR = $(MSDK_LIBS)/Boards/$(MCU_VARIANT_UPPER)/$(BOARD) + +# Print resolved paths for debugging the build ifneq ($(BUILD_VERBOSE),"") $(info MSDK_ROOT is $(MSDK_ROOT)) $(info MSDK_LIBS is $(MSDK_LIBS)) @@ -55,107 +66,49 @@ $(info ADI_PERIPH is $(ADI_PERIPH)) $(info ADI_MISC_DRIVERS_DIR is $(ADI_MISC_DRIVERS_DIR)) $(info ADI_BOARD_DIR is $(ADI_BOARD_DIR)) $(info MAXIM_PATH is $(MAXIM_PATH)) -$(info MCU_VARIANT_LOWER is $(MCU_VARIANT_LOWER)) +$(info MCU_VARIANT is $(MCU_VARIANT)) $(info DIE_TYPE is $(DIE_TYPE)) endif -# ----------------- -# Sources & Include -# ----------------- -# Define max32 die type for PeriphDriver Includes -# default to me18 for max32690 -# more info: -# https://analogdevicesinc.github.io/msdk//USERGUIDE/#die-types-to-part-numbers +################################################################################ +# INCLUDES & SOURCES +################################################################################ -PERIPH_SRC = $(ADI_PERIPH)/Source -PERIPH_INC = $(ADI_PERIPH)/Include/$(MCU_VARIANT_UPPER) +# MSDK Specific Includes / Sources +MXC_SPI_VERSION := v1 +include ./msdk/Libraries/PeriphDrivers/${MCU_VARIANT_LOWER}_files.mk -INC += -I. -INC += -I../.. -INC += -I$(BUILD) -INC += -I$(BUILD)/genhdr -INC += -I./../../lib/cmsis/inc -INC += -I./boards/ -INC += -I./boards/$(BOARD) -INC += -I./peripherals/ -INC += -I../../lib/mp-readline +# Add MAX32 files to Include / Source paths +INC += $(addprefix -I,${PERIPH_DRIVER_INCLUDE_DIR}) +SRC_MAX32 += ${PERIPH_DRIVER_C_FILES} +SRC_MAX32 += $(CMSIS_ROOT)/Device/Maxim/$(MCU_VARIANT_UPPER)/Source/system_$(MCU_VARIANT_LOWER).c +# Include paths: +# - TOP: CircuitPython root includes +# - ./: Port & Board specific headers +# - CMSIS: ARM CMSIS Device headers +# - BUILD: Generated headers (genhdr) INC += \ - -I$(TOP)/$(BOARD_PATH) \ + -I$(TOP) \ -I$(TOP)/lib/cmsis/inc \ + -I$(TOP)lib/mp-readline \ + -I. \ + -I./boards \ + -I./boards/$(BOARD) \ + -I./peripherals/ \ -I$(CMSIS_ROOT)/Include \ -I$(CMSIS_ROOT)/Device/Maxim/$(MCU_VARIANT_UPPER)/Include \ - -I$(PERIPH_INC) \ - -I$(PERIPH_SRC)/SYS \ - -I$(PERIPH_SRC)/CTB \ - -I$(PERIPH_SRC)/DMA \ - -I$(PERIPH_SRC)/FLC \ - -I$(PERIPH_SRC)/GPIO \ - -I$(PERIPH_SRC)/ICC \ - -I$(PERIPH_SRC)/TMR \ - -I$(PERIPH_SRC)/RTC \ - -I$(PERIPH_SRC)/UART \ - -I$(PERIPH_SRC)/TRNG \ - -I$(PERIPH_SRC)/I2C \ - -I$(PERIPH_SRC)/SPI - -INC += -I$(CMSIS_ROOT)/Device/Maxim/$(MCU_VARIANT_UPPER)/Source/GCC - -SRC_MAX32 += \ - $(CMSIS_ROOT)/Device/Maxim/$(MCU_VARIANT_UPPER)/Source/heap.c \ - $(CMSIS_ROOT)/Device/Maxim/$(MCU_VARIANT_UPPER)/Source/system_$(MCU_VARIANT_LOWER).c \ - $(PERIPH_SRC)/SYS/mxc_assert.c \ - $(PERIPH_SRC)/SYS/mxc_delay.c \ - $(PERIPH_SRC)/SYS/mxc_lock.c \ - $(PERIPH_SRC)/SYS/nvic_table.c \ - $(PERIPH_SRC)/SYS/pins_$(DIE_TYPE).c \ - $(PERIPH_SRC)/SYS/sys_$(DIE_TYPE).c \ - $(PERIPH_SRC)/CTB/ctb_$(DIE_TYPE).c \ - $(PERIPH_SRC)/CTB/ctb_reva.c \ - $(PERIPH_SRC)/CTB/ctb_common.c \ - $(PERIPH_SRC)/DMA/dma_reva.c \ - $(PERIPH_SRC)/DMA/dma_$(DIE_TYPE).c \ - $(PERIPH_SRC)/FLC/flc_common.c \ - $(PERIPH_SRC)/FLC/flc_$(DIE_TYPE).c \ - $(PERIPH_SRC)/FLC/flc_reva.c \ - $(PERIPH_SRC)/GPIO/gpio_common.c \ - $(PERIPH_SRC)/GPIO/gpio_$(DIE_TYPE).c \ - $(PERIPH_SRC)/GPIO/gpio_reva.c \ - $(PERIPH_SRC)/ICC/icc_$(DIE_TYPE).c \ - $(PERIPH_SRC)/ICC/icc_reva.c \ - $(PERIPH_SRC)/RTC/rtc_$(DIE_TYPE).c \ - $(PERIPH_SRC)/RTC/rtc_reva.c \ - $(PERIPH_SRC)/TMR/tmr_common.c \ - $(PERIPH_SRC)/TMR/tmr_revb.c \ - $(PERIPH_SRC)/TMR/tmr_$(DIE_TYPE).c \ - $(PERIPH_SRC)/UART/uart_common.c \ - $(PERIPH_SRC)/UART/uart_$(DIE_TYPE).c \ - $(PERIPH_SRC)/UART/uart_revb.c \ - $(PERIPH_SRC)/TRNG/trng_revb.c \ - $(PERIPH_SRC)/TRNG/trng_$(DIE_TYPE).c \ - $(PERIPH_SRC)/I2C/i2c_$(DIE_TYPE).c \ - $(PERIPH_SRC)/I2C/i2c_reva.c \ - $(PERIPH_SRC)/SPI/spi_$(DIE_TYPE).c \ - $(PERIPH_SRC)/SPI/spi_reva1.c - -# Small source correction for ME10 (MAX32650) -ifeq ($(DIE_TYPE),me10) -SRC_MAX32 := $(filter-out \ - $(PERIPH_SRC)/CTB/ctb_reva.c \ - $(PERIPH_SRC)/CTB/ctb_common.c \ - $(PERIPH_SRC)/CTB/ctb_me10.c, \ - $(SRC_MAX32)) -endif - -ifeq ($(DIE_TYPE),me14) -SRC_MAX32 := $(filter-out \ - $(PERIPH_SRC)/CTB/ctb_reva.c \ - $(PERIPH_SRC)/CTB/ctb_common.c \ - $(PERIPH_SRC)/CTB/ctb_me14.c, \ - $(SRC_MAX32)) -endif - + -I$(CMSIS_ROOT)/Device/Maxim/$(MCU_VARIANT_UPPER)/Source/GCC \ + -I${BUILD} \ + -I${BUILD}/genhdr + +# Source Files: +# - background / mphalport: Circuitpython main port files +# - boards/...: board-specific pin objects and source code +# - peripherals/...: MCU-specific pins, peripherals, and helper code SRC_C += $(SRC_MAX32) \ + background.c \ + mphalport.c \ boards/$(BOARD)/board.c \ boards/$(BOARD)/pins.c \ peripherals/$(MCU_VARIANT_LOWER)/pins.c \ @@ -164,24 +117,41 @@ SRC_C += $(SRC_MAX32) \ peripherals/$(MCU_VARIANT_LOWER)/max32_i2c.c \ peripherals/$(MCU_VARIANT_LOWER)/max32_spi.c -# ******************************************************************************* -### Compiler & Linker Flags ### -COMPILER ?= GCC +# Add TinyUSB sources +INC += -I../../lib/tinyusb/src \ + -I../../supervisor/shared/usb +SRC_C += lib/tinyusb/src/portable/mentor/musb/dcd_musb.c +# Assembly files for startup & supervisor ifeq ($(COMPILER), GCC) - STARTUPFILE = $(CMSIS_ROOT)/Device/Maxim/$(MCU_VARIANT_UPPER)/Source/GCC/startup_$(MCU_VARIANT_LOWER).s -# STARTUPFILE = $(ADI_BOARD_DIR)/Source/startup_$(MCU_VARIANT_LOWER).s +endif +SRC_S_UPPER = supervisor/shared/cpu_regs.S +SRC_S += $(STARTUPFILE) # CircuitPython custom linkerfile (necessary for build steps & filesystems) LINKERFILE = linking/$(MCU_VARIANT_LOWER)_cktpy.ld -LDFLAGS += -nostartfiles -specs=nano.specs + +################################################################################ +# COMPILER & LINKER FLAGS +################################################################################ + +# Debugging flags +# NOTE: DEBUG=1 is temporarily the default +DEBUG ?= 1 +ifeq ($(DEBUG),1) +COPT = -ggdb3 -Og -Os +else +COPT += -Os endif SRC_S += $(STARTUPFILE) SRC_S += shared/runtime/gchelper_thumb2.s SRC_C += shared/runtime/gchelper_native.c +CPU_CORE=cortex-m4 +CFLAGS += $(BASE_CFLAGS) $(INC) $(COPT) -mthumb -mcpu=$(CPU_CORE) -mfloat-abi=softfp \ + -mfpu=fpv4-sp-d16 -Werror -Wall -std=gnu11 -nostartfiles # Needed to compile some MAX32 headers CFLAGS += -D$(MCU_VARIANT_UPPER) \ @@ -197,20 +167,6 @@ CFLAGS += -D$(MCU_VARIANT_UPPER) \ # -DSRAM_ORIGIN \ # -DSRAM_SIZE -CPU_CORE=cortex-m4 -CFLAGS += -mthumb -mcpu=$(CPU_CORE) -mfloat-abi=softfp -mfpu=fpv4-sp-d16 - -# NOTE: Start with DEBUG=1 defaults for now -ifeq ($(DEBUG),) -DEBUG ?= 1 -endif - -ifeq ($(DEBUG),1) -COPT = -ggdb3 -Og -Os -else -COPT += -Os -endif - # TinyUSB CFLAGS CFLAGS += \ -DCFG_TUSB_MCU=OPT_MCU_$(MCU_VARIANT_UPPER) \ @@ -224,19 +180,6 @@ CFLAGS += \ -DCFG_TUD_VENDOR_RX_BUFSIZE=1024 \ -DCFG_TUD_VENDOR_TX_BUFSIZE=1024 -# Add TinyUSB sources -INC += -I../../lib/tinyusb/src -INC += -I../../supervisor/shared/usb -SRC_C += lib/tinyusb/src/portable/mentor/musb/dcd_musb.c - -# Add port sources incl. any board functions -SRC_C += \ - boards/$(BOARD)/board.c \ - background.c \ - mphalport.c \ - -CFLAGS += $(INC) -Werror -Wall -std=gnu11 -nostartfiles $(BASE_CFLAGS) $(COPT) - # Suppress some errors for MSDK # cast-align warning will be suppressed; # it gets generated by CircuitPy's TLSF memory allocator lib @@ -251,18 +194,29 @@ CFLAGS += -Wno-error=unused-parameter \ -Wno-error=nested-externs \ -Wno-error=sign-compare \ -Wno-cast-align \ - -Wno-sign-compare \ + -Wno-sign-compare +# Entry point ENTRY = Reset_Handler -LDFLAGS += $(CFLAGS) --entry $(ENTRY) -Wl,-nostdlib -Wl,-T,$(LINKERFILE) -Wl,-Map=$@.map -Wl,-cref -Wl,-gc-sections -LIBS := -lgcc -lc +# Libraries +LIBS := -lgcc -lc # If not using CKTPY mathlib, use toolchain mathlib ifndef INTERNAL_LIBM LIBS += -lm endif -# ******************************************************************************* +# Linker flags +ifeq ($(COMPILER), GCC) +LDFLAGS += -nostartfiles -specs=nano.specs +endif +LDFLAGS += $(CFLAGS) --entry $(ENTRY) -Wl,-nostdlib -Wl,-T,$(LINKERFILE) \ + -Wl,-Map=$@.map -Wl,-cref -Wl,-gc-sections + +################################################################################ +# MAX32 BUILD RULES +################################################################################ + ### PORT-DEFINED BUILD RULES ### # This section attempts to build the Python core, the supervisor, and any # port-provided source code. @@ -289,9 +243,31 @@ SRC_QSTR_PREPROCESSOR += # Default build target all: $(BUILD)/firmware.elf $(BUILD)/firmware.hex $(BUILD)/firmware.bin +pristine: + $(MAKE) -s clean + $(MAKE) --no-print-directory all + clean-all: rm -rf build-* +$(BUILD)/firmware.elf: $(OBJ) + $(STEPECHO) "LINK $@" + $(Q)echo $^ > $(BUILD)/firmware.objs + $(Q)$(CC) -o $@ $(LDFLAGS) @$(BUILD)/firmware.objs -Wl,--print-memory-usage -Wl,--start-group $(LIBS) -Wl,--end-group + $(Q)$(SIZE) $@ | $(PYTHON) $(TOP)/tools/build_memory_info.py $@.map $(BUILD) + +$(BUILD)/firmware.hex: $(BUILD)/firmware.elf + $(STEPECHO) "Create $@" + $(Q)$(OBJCOPY) -O ihex $^ $@ + +$(BUILD)/firmware.bin: $(BUILD)/firmware.elf + $(STEPECHO) "Create $@" + $(Q)$(OBJCOPY) -O binary $^ $@ + +################################################################################ +# MAX32 FLASHING RULES +################################################################################ + # Optional flash option when running within an installed MSDK to use OpenOCD # Mainline OpenOCD does not yet have the MAX32's flash algorithm integrated. # If the MSDK is installed, flash-msdk can be run to utilize the the modified @@ -319,20 +295,7 @@ COMMAND_FILE := tools/flash_max32.jlink flash-jlink: $(BUILD)/firmware.bin @$(JLINKEXE) -device $(MCU_VARIANT_UPPER) -NoGui 1 -CommandFile ${COMMAND_FILE} -$(BUILD)/firmware.elf: $(OBJ) - $(STEPECHO) "LINK $@" - $(Q)echo $^ > $(BUILD)/firmware.objs - $(Q)$(CC) -o $@ $(LDFLAGS) @$(BUILD)/firmware.objs -Wl,--print-memory-usage -Wl,--start-group $(LIBS) -Wl,--end-group - $(Q)$(SIZE) $@ | $(PYTHON) $(TOP)/tools/build_memory_info.py $@.map $(BUILD) - -$(BUILD)/firmware.hex: $(BUILD)/firmware.elf - $(STEPECHO) "Create $@" - $(Q)$(OBJCOPY) -O ihex $^ $@ - -$(BUILD)/firmware.bin: $(BUILD)/firmware.elf - $(STEPECHO) "Create $@" - $(Q)$(OBJCOPY) -O binary $^ $@ - -# ******************************************************************************* -### CKTPY BUILD RULES ### +################################################################################ +# CKTPY MAIN BUILD RULES +################################################################################ include $(TOP)/py/mkrules.mk From d616c4c8a99ee8a2813f3604d9231477d5df7c49 Mon Sep 17 00:00:00 2001 From: Brandon-Hurst Date: Sat, 17 Jan 2026 22:55:25 -0800 Subject: [PATCH 11/23] ports: analog: rename linkerscript for max32665 Signed-off-by: Brandon-Hurst --- .../analog/linking/{max32666_cktpy.ld => max32665_cktpy.ld} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename ports/analog/linking/{max32666_cktpy.ld => max32665_cktpy.ld} (98%) diff --git a/ports/analog/linking/max32666_cktpy.ld b/ports/analog/linking/max32665_cktpy.ld similarity index 98% rename from ports/analog/linking/max32666_cktpy.ld rename to ports/analog/linking/max32665_cktpy.ld index 639be448cea..fe0e2a9df74 100644 --- a/ports/analog/linking/max32666_cktpy.ld +++ b/ports/analog/linking/max32665_cktpy.ld @@ -5,10 +5,10 @@ * SPDX-License-Identifier: MIT */ -/* +/* * FLASH_FIRMWARE: 1024 KiB - 128 KiB = 896 KiB - * - * Start & Size for FLASH_FIRMWARE and RAM MUST be raw numbers + * + * Start & Size for FLASH_FIRMWARE and RAM MUST be raw numbers * b/c FLASH_FIMRWARE is parsed with Python build_memory_info.py */ MEMORY { From d115d224e83e2a0719a93daaeb45bbb129d2306a Mon Sep 17 00:00:00 2001 From: Brandon-Hurst Date: Sat, 17 Jan 2026 23:00:33 -0800 Subject: [PATCH 12/23] ports: analog: Improve supervisor portability - *usb.c*: Place USB hardware clock / power into separate init_usb functions. - *internal_flash.c*: Move Flash and Instruction Cache Controller operations into different functions for different targets. - *port.c*: Create macros abstracting RTC alarms & enables for different register structures. Signed-off-by: Brandon-Hurst --- ports/analog/supervisor/internal_flash.c | 80 ++++++++++++++++++------ ports/analog/supervisor/port.c | 61 ++++++++++++------ ports/analog/supervisor/usb.c | 30 +++++++-- 3 files changed, 128 insertions(+), 43 deletions(-) diff --git a/ports/analog/supervisor/internal_flash.c b/ports/analog/supervisor/internal_flash.c index c20e5d78f12..e9cda0d9a6f 100644 --- a/ports/analog/supervisor/internal_flash.c +++ b/ports/analog/supervisor/internal_flash.c @@ -67,14 +67,48 @@ static const flash_layout_t flash_layout[] = { }; // must be able to hold a full page (for re-writing upon erase) static uint32_t page_buffer[FLASH_PAGE_SIZE / 4] = {0x0}; + +static void icc_flush(void) { + // Flush all instruction cache + // ME18 has bug where top-level sysctrl flush bit only works once. + // Have to use low-level flush bits for each ICC instance. + MXC_ICC_Flush(MXC_ICC0); +} +static void icc_enable(void) { + MXC_ICC_Enable(MXC_ICC0); +} +static void icc_disable(void) { + MXC_ICC_Disable(MXC_ICC0); +} + +static void flash_lock(void) { + MXC_FLC0->ctrl |= MXC_S_FLC_REVA_CTRL_UNLOCK_LOCKED; + MXC_FLC1->ctrl |= MXC_S_FLC_REVA_CTRL_UNLOCK_LOCKED; +} + #elif defined(MAX32650) static const flash_layout_t flash_layout[] = { { 0x10000000, FLASH_PAGE_SIZE, 192}, }; // must be able to hold a full page (for re-writing upon erase) static uint32_t page_buffer[FLASH_PAGE_SIZE / 4] = {0x0}; + +static void icc_flush(void) { + // Flush all instruction cache + MXC_ICC_Flush(); +} +static void icc_enable(void) { + MXC_ICC_Enable(); +} +static void icc_disable(void) { + MXC_ICC_Disable(); +} + +static void flash_lock(void) { + MXC_FLC->ctrl |= MXC_S_FLC_REVA_CTRL_UNLOCK_LOCKED; +} #elif defined(MAX32665) -// MAX32666 has two flash banks, but we do not actually need to +// MAX32666 has two flash banks, but we do not actually need to // treat them separately static const flash_layout_t flash_layout[] = { { 0x10000000, FLASH_PAGE_SIZE, 64}, @@ -82,10 +116,28 @@ static const flash_layout_t flash_layout[] = { }; // must be able to hold a full page (for re-writing upon erase) static uint32_t page_buffer[FLASH_PAGE_SIZE / 4] = {0x0}; + +static void icc_flush(void) { + // Flush all instruction cache + MXC_ICC_Flush(); +} +static void icc_enable(void) { + MXC_ICC_Enable(); +} +static void icc_disable(void) { + MXC_ICC_Disable(); +} + +static void flash_lock(void) { + MXC_FLC0->cn |= MXC_S_FLC_REVA_CTRL_UNLOCK_LOCKED; + MXC_FLC1->cn |= MXC_S_FLC_REVA_CTRL_UNLOCK_LOCKED; +} #else #error "Invalid BOARD. Please set BOARD equal to any board under 'boards/'." #endif + + static inline int32_t block2addr(uint32_t block) { if (block >= 0 && block < INTERNAL_FLASH_FILESYSTEM_NUM_BLOCKS) { return CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_START_ADDR + block * FILESYSTEM_BLOCK_SIZE; @@ -110,9 +162,9 @@ int flash_get_sector_info(uint32_t addr, uint32_t *start_addr, uint32_t *size) { flash_layout_t bank = flash_layout[i]; // Determine if the flash bank is a hit for this address - if ((addr >= bank.base_addr) && + if ((addr >= bank.base_addr) && (addr < bank.base_addr + bank.sector_size * bank.num_sectors) - ) { + ) { // Assign the sector index assuming uniform sector sizes sector_index = i * bank.num_sectors + ((addr - bank.base_addr) / bank.sector_size); *start_addr = flash_layout[0].base_addr + (sector_index * bank.sector_size); @@ -137,12 +189,7 @@ uint32_t supervisor_flash_get_block_count(void) { } void port_internal_flash_flush(void) { - - // Flush all instruction cache - // ME18 has bug where top-level sysctrl flush bit only works once. - // Have to use low-level flush bits for each ICC instance. - MXC_ICC_Flush(MXC_ICC0); - MXC_ICC_Flush(MXC_ICC1); + icc_flush(); // Clear the line fill buffer by reading 2 pages from flash volatile uint32_t *line_addr; @@ -199,7 +246,7 @@ mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t block_num, blocks_left = (page_size - (dest_addr - page_start)) / FILESYSTEM_BLOCK_SIZE; count = MIN(num_blocks, blocks_left); - MXC_ICC_Disable(MXC_ICC0); + icc_disable(); // Buffer the page of flash to erase MXC_FLC_Read(page_start, page_buffer, page_size); @@ -209,11 +256,7 @@ mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t block_num, error = MXC_FLC_PageErase(dest_addr); ); if (error != E_NO_ERROR) { - // lock flash & reset - MXC_FLC0->ctrl = (MXC_FLC0->ctrl & ~MXC_F_FLC_REVA_CTRL_UNLOCK) | MXC_S_FLC_REVA_CTRL_UNLOCK_LOCKED; - #if defined(MAX32666) - MXC_FLC1->ctrl = (MXC_FLC1->ctrl & ~MXC_F_FLC_REVA_CTRL_UNLOCK) | MXC_S_FLC_REVA_CTRL_UNLOCK_LOCKED; - #endif + flash_lock(); reset_into_safe_mode(SAFE_MODE_FLASH_WRITE_FAIL); } @@ -228,14 +271,11 @@ mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t block_num, ); if (error != E_NO_ERROR) { // lock flash & reset - MXC_FLC0->ctrl = (MXC_FLC0->ctrl & ~MXC_F_FLC_REVA_CTRL_UNLOCK) | MXC_S_FLC_REVA_CTRL_UNLOCK_LOCKED; - #if defined(MAX32666) - MXC_FLC1->ctrl = (MXC_FLC1->ctrl & ~MXC_F_FLC_REVA_CTRL_UNLOCK) | MXC_S_FLC_REVA_CTRL_UNLOCK_LOCKED; - #endif + flash_lock(); reset_into_safe_mode(SAFE_MODE_FLASH_WRITE_FAIL); } - MXC_ICC_Enable(MXC_ICC0); + icc_enable(); block_num += count; src += count * FILESYSTEM_BLOCK_SIZE; diff --git a/ports/analog/supervisor/port.c b/ports/analog/supervisor/port.c index e95deaba2a8..0888605a723 100644 --- a/ports/analog/supervisor/port.c +++ b/ports/analog/supervisor/port.c @@ -48,6 +48,36 @@ // true random number generator, TRNG #include "trng.h" +// Define macros for RTC flags for portability +#if defined(MAX32690) +#define TOD_FLAG MXC_F_RTC_CTRL_TOD_ALARM +#define SSEC_FLAG MXC_F_RTC_CTRL_SSEC_ALARM +#define RDY_FLAG MXC_F_RTC_CTRL_RDY + +#define TOD_ENABLE MXC_F_RTC_CTRL_TOD_ALARM_IE +#define SSEC_ENABLE MXC_F_RTC_CTRL_SSEC_ALARM_IE +#define RDY_ENABLE MXC_F_RTC_CTRL_RDY_IE +#define RTC_ENABLE MXC_F_RTC_CTRL_EN +#elif defined(MAX32650) +#define TOD_FLAG MXC_F_RTC_CTRL_TOD_ALARM_FL +#define SSEC_FLAG MXC_F_RTC_CTRL_SSEC_ALARM_FL +#define RDY_FLAG MXC_F_RTC_CTRL_READY + +#define TOD_ENABLE MXC_F_RTC_CTRL_TOD_ALARM_EN +#define SSEC_ENABLE MXC_F_RTC_CTRL_SSEC_ALARM_EN +#define RDY_ENABLE MXC_F_RTC_CTRL_READY_INT_EN +#define RTC_ENABLE MXC_F_RTC_CTRL_ENABLE +#elif defined(MAX32665) +#define TOD_FLAG MXC_F_RTC_CTRL_ALDF +#define SSEC_FLAG MXC_F_RTC_CTRL_ALSF +#define RDY_FLAG MXC_F_RTC_CTRL_RDY + +#define TOD_ENABLE MXC_F_RTC_CTRL_ADE +#define SSEC_ENABLE MXC_F_RTC_CTRL_ASE +#define RDY_ENABLE MXC_F_RTC_CTRL_RDYE +#define RTC_ENABLE MXC_F_RTC_CTRL_RTCE +#endif + // msec to RTC subsec ticks (4 kHz) /* Converts a time in milleseconds to equivalent RSSA register value */ #define MSEC_TO_SS_ALARM(x) (0 - ((x * 4096) / 1000)) @@ -100,12 +130,6 @@ safe_mode_t port_init(void) { } } - // Enable clock to RTC peripheral - MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_ERTCO_EN; - while (!(MXC_GCR->clkctrl & MXC_F_GCR_CLKCTRL_ERTCO_RDY)) { - ; - } - NVIC_EnableIRQ(RTC_IRQn); NVIC_EnableIRQ(USB_IRQn); @@ -116,9 +140,9 @@ safe_mode_t port_init(void) { ; // enable 1 sec RTC SSEC alarm - MXC_RTC_DisableInt(MXC_F_RTC_CTRL_SSEC_ALARM_IE); + MXC_RTC_DisableInt(SSEC_ENABLE); MXC_RTC_SetSubsecondAlarm(MSEC_TO_SS_ALARM(1000)); - MXC_RTC_EnableInt(MXC_F_RTC_CTRL_SSEC_ALARM_IE); + MXC_RTC_EnableInt(SSEC_ENABLE); // Enable RTC while (MXC_RTC_Start() != E_SUCCESS) { @@ -142,14 +166,14 @@ void RTC_IRQHandler(void) { int flags = MXC_RTC_GetFlags(); switch (flags) { - case MXC_F_RTC_CTRL_SSEC_ALARM: - MXC_RTC_ClearFlags(MXC_F_RTC_CTRL_SSEC_ALARM); + case SSEC_FLAG: + MXC_RTC_ClearFlags(SSEC_FLAG); break; - case MXC_F_RTC_CTRL_TOD_ALARM: - MXC_RTC_ClearFlags(MXC_F_RTC_CTRL_TOD_ALARM); + case TOD_FLAG: + MXC_RTC_ClearFlags(TOD_FLAG); break; - case MXC_F_RTC_CTRL_RDY: - MXC_RTC_ClearFlags(MXC_F_RTC_CTRL_RDY); + case RDY_FLAG: + MXC_RTC_ClearFlags(RDY_FLAG); break; default: break; @@ -217,7 +241,7 @@ uint32_t port_get_saved_word(void) { uint64_t port_get_raw_ticks(uint8_t *subticks) { // Ensure we can read from ssec register as soon as we can // MXC function does cross-tick / busy checking of RTC controller - if (MXC_RTC->ctrl & MXC_F_RTC_CTRL_EN) { + if (MXC_RTC->ctrl & RTC_ENABLE) { // NOTE: RTC_GetTime always returns BUSY if RTC is not running while ((MXC_RTC_GetTime(&sec, &subsec)) != E_NO_ERROR) { ; @@ -261,8 +285,7 @@ void port_interrupt_after_ticks(uint32_t ticks) { ticks_msec = (ticks / TICKS_PER_SEC) * 1000; // Disable RTC interrupts - MXC_RTC_DisableInt(MXC_F_RTC_CTRL_SSEC_ALARM_IE | - MXC_F_RTC_CTRL_TOD_ALARM_IE | MXC_F_RTC_CTRL_RDY_IE); + MXC_RTC_DisableInt(SSEC_ENABLE | TOD_ENABLE | RDY_ENABLE); // Stop RTC & store current time & ticks port_get_raw_ticks(NULL); @@ -275,14 +298,14 @@ void port_interrupt_after_ticks(uint32_t ticks) { while (MXC_RTC_SetSubsecondAlarm(MSEC_TO_SS_ALARM(ticks_msec)) != E_SUCCESS) { } - MXC_RTC_EnableInt(MXC_F_RTC_CTRL_SSEC_ALARM_IE); + MXC_RTC_EnableInt(SSEC_ENABLE); } void port_idle_until_interrupt(void) { #if CIRCUITPY_RTC // Check if alarm triggers before we even got here - if (MXC_RTC_GetFlags() == (MXC_F_RTC_CTRL_TOD_ALARM | MXC_F_RTC_CTRL_SSEC_ALARM)) { + if (MXC_RTC_GetFlags() == (TOD_FLAG | SSEC_FLAG)) { return; } #endif diff --git a/ports/analog/supervisor/usb.c b/ports/analog/supervisor/usb.c index 803569cac09..465caa58cb1 100644 --- a/ports/analog/supervisor/usb.c +++ b/ports/analog/supervisor/usb.c @@ -15,6 +15,31 @@ // max32 includes #include "max32_port.h" +#if defined(MAX32690) +static void init_usb(void) { + // Enable 120 MHz IPO, then 0.9V LDO supplying USB + MXC_SYS_ClockSourceEnable(MXC_SYS_CLOCK_IPO); + MXC_MCR->ldoctrl |= MXC_F_MCR_LDOCTRL_0P9EN; + + MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_USB); + MXC_SYS_Reset_Periph(MXC_SYS_RESET0_USB); +} +#elif defined(MAX32650) +static void init_usb(void) { + // Enable the 96MHz clock, then enable USB + MXC_GCR->clk_ctrl |= MXC_F_GCR_CLK_CTRL_HIRC96_EN; + MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_USB); + MXC_SYS_Reset_Periph(MXC_SYS_RESET_USB); +} +#elif defined(MAX32665) +static void init_usb(void) { + // Enable the 96MHz clock, then enable USB + MXC_GCR->clkcn |= MXC_F_GCR_CLKCN_HIRC96M_EN; + MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_USB); + MXC_SYS_Reset_Periph(MXC_SYS_RESET_USB); +} +#endif + void init_usb_hardware(void) { // USB GPIOs are non-configurable on MAX32 devices // No need to add them to the never_reset list for mcu/Pin API. @@ -22,10 +47,7 @@ void init_usb_hardware(void) { // 1 ms SysTick initialized in board.c // Enable requisite clocks & power for USB - MXC_SYS_ClockSourceEnable(MXC_SYS_CLOCK_IPO); - MXC_MCR->ldoctrl |= MXC_F_MCR_LDOCTRL_0P9EN; - MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_USB); - MXC_SYS_Reset_Periph(MXC_SYS_RESET0_USB); + init_usb(); // Supervisor calls TinyUSB's dcd_init, // which initializes the USB PHY. From 5a3e65618d0ef80adbf2a51a54d65e3a32460b32 Mon Sep 17 00:00:00 2001 From: Brandon-Hurst Date: Sat, 17 Jan 2026 23:05:48 -0800 Subject: [PATCH 13/23] ports: analog: Define SUBSEC_PER_TICK for MAX32665 & MAX32650 Signed-off-by: Brandon-Hurst --- ports/analog/max32_port.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/ports/analog/max32_port.h b/ports/analog/max32_port.h index 6da703231dc..c12e9fcc82c 100644 --- a/ports/analog/max32_port.h +++ b/ports/analog/max32_port.h @@ -27,6 +27,9 @@ #include "peripherals/max32690/max32_i2c.h" #include "peripherals/max32690/max32_spi.h" +// 12-bit ssec register, ticks @ 4096 Hz +#define SUBSEC_PER_TICK 4 + /** START: GPIO4 Handling specific to MAX32690 */ #define GPIO4_PIN_MASK 0x00000003 #define GPIO4_RESET_MASK 0xFFFFFF77 @@ -60,6 +63,9 @@ #include "system_max32650.h" #include "max32650.h" +// 12-bit ssec register, ticks @ 4096 Hz +#define SUBSEC_PER_TICK 4 + // UART Ports & pins #include "peripherals/max32650/max32_uart.h" #include "peripherals/max32650/max32_i2c.h" @@ -70,6 +76,9 @@ #include "system_max32665.h" #include "max32665.h" +// 12-bit ssec register, ticks @ 4096 Hz +#define SUBSEC_PER_TICK 4 + // UART Ports & pins #include "peripherals/max32665/max32_uart.h" #include "peripherals/max32665/max32_i2c.h" @@ -91,9 +100,4 @@ extern uint32_t SystemCoreClock; // Tick timer should be 1/1024 s. RTC Oscillator is usually 32.768 kHz ERTCO. #define TICKS_PER_SEC 1024 -#ifdef MAX32690 -// 12-bit ssec register, ticks @ 4096 Hz -#define SUBSEC_PER_TICK 4 -#endif - #endif // MAX32_PORT_H From de5d3993fb62249ddc760993b5dfd194aff7040a Mon Sep 17 00:00:00 2001 From: Brandon-Hurst Date: Sat, 17 Jan 2026 23:07:30 -0800 Subject: [PATCH 14/23] ports: analog: Fix pin issues for MAX32650 & MAX32665 - Add MCU-specific includes in peripherals/pins.h for MAX32650 & MAX32665 - Fix some issues with SPI pins not matching the datasheet / MSDK for MAX32650 / MAX32665 Signed-off-by: Brandon-Hurst --- ports/analog/peripherals/max32650/max32_spi.c | 8 +++----- ports/analog/peripherals/max32665/max32_spi.c | 6 +++--- ports/analog/peripherals/pins.h | 6 +++++- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/ports/analog/peripherals/max32650/max32_spi.c b/ports/analog/peripherals/max32650/max32_spi.c index c8563dd8fe2..8c97c486b67 100644 --- a/ports/analog/peripherals/max32650/max32_spi.c +++ b/ports/analog/peripherals/max32650/max32_spi.c @@ -15,8 +15,9 @@ const mxc_gpio_cfg_t spi_maps[NUM_SPI] = { // SPI0 - { MXC_GPIO2, (MXC_GPIO_PIN_27 | MXC_GPIO_PIN_28 | MXC_GPIO_PIN_29), - MXC_GPIO_FUNC_ALT2, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + // NOTE: SPI0 CS not enabled automatically + { MXC_GPIO3, (MXC_GPIO_PIN_1 | MXC_GPIO_PIN_2 | MXC_GPIO_PIN_3), + MXC_GPIO_FUNC_ALT1, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, // SPI1 { MXC_GPIO1, (MXC_GPIO_PIN_26 | MXC_GPIO_PIN_28 | MXC_GPIO_PIN_29), MXC_GPIO_FUNC_ALT1, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, @@ -26,9 +27,6 @@ const mxc_gpio_cfg_t spi_maps[NUM_SPI] = { // SPI3 { MXC_GPIO0, (MXC_GPIO_PIN_16 | MXC_GPIO_PIN_20 | MXC_GPIO_PIN_21), MXC_GPIO_FUNC_ALT1, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, - // SPI4 - { MXC_GPIO1, (MXC_GPIO_PIN_1 | MXC_GPIO_PIN_2 | MXC_GPIO_PIN_3), - MXC_GPIO_FUNC_ALT1, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, }; int pinsToSpi(const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, diff --git a/ports/analog/peripherals/max32665/max32_spi.c b/ports/analog/peripherals/max32665/max32_spi.c index 2a97768bdc5..993a8d7f52e 100644 --- a/ports/analog/peripherals/max32665/max32_spi.c +++ b/ports/analog/peripherals/max32665/max32_spi.c @@ -13,17 +13,17 @@ #include "py/runtime.h" #include "py/mperrno.h" -// Assuming the use of MAP_A in MSDK, since all documentation +// Assuming the use of MAP_A in MSDK, since all documentation // states the GPIO maps are the same const mxc_gpio_cfg_t spi_maps[NUM_SPI] = { // SPI0A { MXC_GPIO1, - (MXC_GPIO_PIN_9 | MXC_GPIO_PIN_10 | MXC_GPIO_PIN_11, MXC_GPIO_PIN_12, MXC_GPIO_PIN_13), + (MXC_GPIO_PIN_9 | MXC_GPIO_PIN_10 | MXC_GPIO_PIN_11 | MXC_GPIO_PIN_12 | MXC_GPIO_PIN_13), MXC_GPIO_FUNC_ALT1, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, // SPI1 { MXC_GPIO0, - (MXC_GPIO_PIN_17 | MXC_GPIO_PIN_18 | MXC_GPIO_PIN_19, MXC_GPIO_PIN_20, MXC_GPIO_PIN_21), + (MXC_GPIO_PIN_17 | MXC_GPIO_PIN_18 | MXC_GPIO_PIN_19 | MXC_GPIO_PIN_20 | MXC_GPIO_PIN_21), MXC_GPIO_FUNC_ALT2, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, // SPI2 { MXC_GPIO0, diff --git a/ports/analog/peripherals/pins.h b/ports/analog/peripherals/pins.h index 3bd7d02bf46..e649418fca9 100644 --- a/ports/analog/peripherals/pins.h +++ b/ports/analog/peripherals/pins.h @@ -31,6 +31,10 @@ extern const mp_obj_type_t mcu_pin_type; // for non-connected pins #define NO_PIN 0xFF -#ifdef MAX32690 +#if defined(MAX32690) #include "max32690/pins.h" +#elif defined(MAX32650) +#include "max32650/pins.h" +#elif defined(MAX32665) +#include "max32665/pins.h" #endif From b4f14e22779459ae82afbf9efca48c79a3cc75cb Mon Sep 17 00:00:00 2001 From: Brandon-Hurst Date: Sat, 17 Jan 2026 23:11:59 -0800 Subject: [PATCH 15/23] ports: analog: Improve common-hal portability for digitalio & microcontroller - *microcontroller/Pin.c*: Use mxc_gpio_reva_regs_t for standardizing different GPIO register structures. - *microcontroller/Processor.c*: - Guard MAX32690 GPIO4 specific operations with preproc macros. - Use mxc_gpio_reva_regs_t for direct register operations to improve portability. Signed-off-by: Brandon-Hurst --- .../common-hal/digitalio/DigitalInOut.c | 56 ++++++++++--------- ports/analog/common-hal/microcontroller/Pin.c | 22 +++++--- .../common-hal/microcontroller/Processor.c | 4 ++ 3 files changed, 47 insertions(+), 35 deletions(-) diff --git a/ports/analog/common-hal/digitalio/DigitalInOut.c b/ports/analog/common-hal/digitalio/DigitalInOut.c index 93e2242fbb6..69768413d89 100644 --- a/ports/analog/common-hal/digitalio/DigitalInOut.c +++ b/ports/analog/common-hal/digitalio/DigitalInOut.c @@ -10,6 +10,7 @@ #include "max32_port.h" #include "gpio_reva.h" +#include "gpio_reva_regs.h" #include "mxc_errors.h" extern mxc_gpio_regs_t *gpio_ports[NUM_GPIO_PORTS]; @@ -60,13 +61,7 @@ digitalinout_result_t common_hal_digitalio_digitalinout_switch_to_input( int err = E_NO_ERROR; - if (self->pin->port == 4) { - // Set GPIO(s) to input mode - MXC_MCR->gpio4_ctrl &= ~GPIO4_OUTEN_MASK(mask); - MXC_MCR->outen &= ~GPIO4_AFEN_MASK(mask); - } else { - err = MXC_GPIO_RevA_SetAF((mxc_gpio_reva_regs_t *)port, MXC_GPIO_FUNC_IN, mask); - } + err = MXC_GPIO_RevA_SetAF((mxc_gpio_reva_regs_t *)port, MXC_GPIO_FUNC_IN, mask); if (err != E_NO_ERROR) { return DIGITALINOUT_PIN_BUSY; } @@ -82,12 +77,7 @@ digitalinout_result_t common_hal_digitalio_digitalinout_switch_to_output( self->open_drain = (drive_mode == DRIVE_MODE_OPEN_DRAIN); // Set GPIO(s) to output mode - if (self->pin->port == 4) { - MXC_MCR->gpio4_ctrl |= GPIO4_OUTEN_MASK(mask); - MXC_MCR->outen &= ~GPIO4_AFEN_MASK(mask); - } else { - MXC_GPIO_RevA_SetAF((mxc_gpio_reva_regs_t *)port, MXC_GPIO_FUNC_OUT, mask); - } + MXC_GPIO_RevA_SetAF((mxc_gpio_reva_regs_t *)port, MXC_GPIO_FUNC_OUT, mask); common_hal_digitalio_digitalinout_set_value(self, value); @@ -97,7 +87,7 @@ digitalinout_result_t common_hal_digitalio_digitalinout_switch_to_output( digitalio_direction_t common_hal_digitalio_digitalinout_get_direction( digitalio_digitalinout_obj_t *self) { - mxc_gpio_regs_t *port = gpio_ports[self->pin->port]; + mxc_gpio_reva_regs_t *port = (mxc_gpio_reva_regs_t *)gpio_ports[self->pin->port]; uint32_t mask = self->pin->mask; // Open drain must be considered output for CircuitPython API to work properly @@ -105,7 +95,16 @@ digitalio_direction_t common_hal_digitalio_digitalinout_get_direction( return DIRECTION_OUTPUT; } - if (self->pin->port < 4) { + #ifdef MAX32690 + if (self->pin->port == 4) { + if (MXC_MCR->gpio4_ctrl & GPIO4_OUTEN_MASK(mask)) { + return DIRECTION_OUTPUT; + } else { + return DIRECTION_INPUT; + } + } else + #endif + { // Check that I/O mode is enabled and we don't have in AND out on at the same time MP_STATIC_ASSERT_NONCONSTEXPR(!((port->en0 & mask) && (port->inen & mask) && (port->outen & mask))); @@ -117,12 +116,6 @@ digitalio_direction_t common_hal_digitalio_digitalinout_get_direction( } else { return DIRECTION_INPUT; } - } else { - if (MXC_MCR->gpio4_ctrl & GPIO4_OUTEN_MASK(mask)) { - return DIRECTION_OUTPUT; - } else { - return DIRECTION_INPUT; - } } } @@ -145,10 +138,13 @@ void common_hal_digitalio_digitalinout_set_value( } else { // can't use common_hal_switch_to_output b/c it calls this function // set the GPIO to output, low + #ifdef MAX32690 if (self->pin->port == 4) { MXC_MCR->gpio4_ctrl |= GPIO4_OUTEN_MASK(mask); MXC_MCR->outen &= ~GPIO4_AFEN_MASK(mask); - } else { + } else + #endif + { MXC_GPIO_RevA_SetAF((mxc_gpio_reva_regs_t *)port, MXC_GPIO_FUNC_OUT, mask); } MXC_GPIO_OutClr(port, mask); @@ -174,9 +170,11 @@ bool common_hal_digitalio_digitalinout_get_value(digitalio_digitalinout_obj_t *s } if (dir == DIRECTION_INPUT) { + #ifdef MAX32690 if (self->pin->port == 4) { return (bool)(MXC_MCR->gpio4_ctrl & GPIO4_DATAIN_MASK(mask)); } + #endif return MXC_GPIO_InGet(port, mask) && mask; } else { return MXC_GPIO_OutGet(port, mask) && mask; @@ -210,9 +208,10 @@ digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode( digitalinout_result_t common_hal_digitalio_digitalinout_set_pull( digitalio_digitalinout_obj_t *self, digitalio_pull_t pull) { - mxc_gpio_regs_t *port = gpio_ports[self->pin->port]; + mxc_gpio_reva_regs_t *port = (mxc_gpio_reva_regs_t *)gpio_ports[self->pin->port]; uint32_t mask = self->pin->mask; + #ifdef MAX32690 // GPIO4 handling if (self->pin->port == 4) { switch (pull) { @@ -236,7 +235,9 @@ digitalinout_result_t common_hal_digitalio_digitalinout_set_pull( break; } return DIGITALINOUT_OK; - } else { + } else + #endif + { // padctrl registers only work in input mode if ((mask & port->en0) & (mask & ~(port->outen))) { // PULL_NONE, PULL_UP, or PULL_DOWN @@ -268,12 +269,13 @@ digitalinout_result_t common_hal_digitalio_digitalinout_set_pull( digitalio_pull_t common_hal_digitalio_digitalinout_get_pull( digitalio_digitalinout_obj_t *self) { - mxc_gpio_regs_t *port = gpio_ports[self->pin->port]; + mxc_gpio_reva_regs_t *port = (mxc_gpio_reva_regs_t *)gpio_ports[self->pin->port]; uint32_t mask = self->pin->mask; bool pin_padctrl0 = (port->padctrl0) & (mask); bool pin_padctrl1 = (port->padctrl1) & (mask); + #ifdef MAX32690 if (self->pin->port == 4) { if (MXC_MCR->gpio4_ctrl & GPIO4_PULLDIS_MASK(mask)) { return PULL_NONE; @@ -284,7 +286,9 @@ digitalio_pull_t common_hal_digitalio_digitalinout_get_pull( return PULL_DOWN; } } - } else { + } else + #endif + { if ((pin_padctrl0) && !(pin_padctrl1)) { return PULL_UP; } else if (!(pin_padctrl0) && pin_padctrl1) { diff --git a/ports/analog/common-hal/microcontroller/Pin.c b/ports/analog/common-hal/microcontroller/Pin.c index 83e2f3b9c3a..49ee5eafb0c 100644 --- a/ports/analog/common-hal/microcontroller/Pin.c +++ b/ports/analog/common-hal/microcontroller/Pin.c @@ -13,6 +13,7 @@ #include "max32_port.h" #include "common-hal/microcontroller/Pin.h" +#include "gpio_reva_regs.h" static uint32_t claimed_pins[NUM_GPIO_PORTS]; @@ -41,29 +42,32 @@ void reset_pin_number(uint8_t pin_port, uint8_t pin_pad) { return; } + // Cast to REVA Regs for portability + mxc_gpio_reva_regs_t *gpio_regs = (mxc_gpio_reva_regs_t *)gpio_ports[pin_port]; + uint32_t mask = 1 << (pin_pad); /** START: RESET LOGIC for GPIOs */ // Switch to I/O mode first - gpio_ports[pin_port]->en0_set = mask; + gpio_regs->en0_set = mask; // set GPIO configuration enable bits to I/O - gpio_ports[pin_port]->en0_clr = mask; - gpio_ports[pin_port]->en1_clr = mask; - gpio_ports[pin_port]->en2_clr = mask; + gpio_regs->en0_clr = mask; + gpio_regs->en1_clr = mask; + gpio_regs->en2_clr = mask; // enable input mode GPIOn_INEN.pin = 1 - gpio_ports[pin_port]->inen |= mask; + gpio_regs->inen |= mask; // High Impedance mode enable (GPIOn_PADCTRL1 = 0, _PADCTRL0 = 0), pu/pd disable - gpio_ports[pin_port]->padctrl0 &= ~mask; - gpio_ports[pin_port]->padctrl1 &= ~mask; + gpio_regs->padctrl0 &= ~mask; + gpio_regs->padctrl1 &= ~mask; // Output mode disable GPIOn_OUTEN = 0 - gpio_ports[pin_port]->outen |= mask; + gpio_regs->outen |= mask; // Interrupt disable GPIOn_INTEN = 0 - gpio_ports[pin_port]->inten &= ~mask; + gpio_regs->inten &= ~mask; /** END: RESET LOGIC for GPIOs */ } diff --git a/ports/analog/common-hal/microcontroller/Processor.c b/ports/analog/common-hal/microcontroller/Processor.c index 3695ecdf671..fda3d62b444 100644 --- a/ports/analog/common-hal/microcontroller/Processor.c +++ b/ports/analog/common-hal/microcontroller/Processor.c @@ -34,7 +34,11 @@ uint32_t common_hal_mcu_processor_get_frequency(void) { // NOTE: COMMON_HAL_MCU_PROCESSOR_UID_LENGTH is defined in mpconfigboard.h // Use this per device to make sure raw_id is an appropriate minimum number of bytes void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { + #if defined(MAX32690) || defined(MAX32665) MXC_SYS_GetUSN(raw_id, NULL); // NULL checksum will not be verified by AES + #elif defined(MAX32650) + MXC_SYS_GetUSN(raw_id, 13); + #endif return; } From d638bbfb45a2113119b1d9c1f6ac887095c10fc4 Mon Sep 17 00:00:00 2001 From: Brandon-Hurst Date: Sun, 18 Jan 2026 18:53:49 -0800 Subject: [PATCH 16/23] ports: analog: Improve supervisor portability in GPIO init - Add gpio_init function to normalize disparate GPIO_Init usage of port parameter - Modify ticks usage in interrupt_after_ticks to fix possible zero result from integer division Signed-off-by: Brandon-Hurst --- ports/analog/max32_port.h | 13 +++++++++++-- ports/analog/peripherals/max32650/gpios.c | 4 ++++ ports/analog/peripherals/max32650/gpios.h | 2 ++ ports/analog/peripherals/max32665/gpios.c | 4 ++++ ports/analog/peripherals/max32665/gpios.h | 2 ++ ports/analog/peripherals/max32690/gpios.c | 4 ++++ ports/analog/peripherals/max32690/gpios.h | 2 ++ ports/analog/supervisor/port.c | 4 ++-- 8 files changed, 31 insertions(+), 4 deletions(-) diff --git a/ports/analog/max32_port.h b/ports/analog/max32_port.h index c12e9fcc82c..5882767a72a 100644 --- a/ports/analog/max32_port.h +++ b/ports/analog/max32_port.h @@ -22,6 +22,9 @@ #include "system_max32690.h" #include "max32690.h" +// GPIO ports & initialization +#include "peripherals/max32690/gpios.h" + // UART Ports & pins #include "peripherals/max32690/max32_uart.h" #include "peripherals/max32690/max32_i2c.h" @@ -66,7 +69,10 @@ // 12-bit ssec register, ticks @ 4096 Hz #define SUBSEC_PER_TICK 4 -// UART Ports & pins +// GPIO ports & initialization +#include "peripherals/max32650/gpios.h" + +// BUSIO Ports & pins #include "peripherals/max32650/max32_uart.h" #include "peripherals/max32650/max32_i2c.h" #include "peripherals/max32650/max32_spi.h" @@ -79,7 +85,10 @@ // 12-bit ssec register, ticks @ 4096 Hz #define SUBSEC_PER_TICK 4 -// UART Ports & pins +// GPIO ports & initialization +#include "peripherals/max32665/gpios.h" + +// BUSIO Ports & pins #include "peripherals/max32665/max32_uart.h" #include "peripherals/max32665/max32_i2c.h" #include "peripherals/max32665/max32_spi.h" diff --git a/ports/analog/peripherals/max32650/gpios.c b/ports/analog/peripherals/max32650/gpios.c index ba3e25a3c2d..2cff60d83ea 100644 --- a/ports/analog/peripherals/max32650/gpios.c +++ b/ports/analog/peripherals/max32650/gpios.c @@ -8,3 +8,7 @@ volatile mxc_gpio_regs_t *gpio_ports[NUM_GPIO_PORTS] = {MXC_GPIO0, MXC_GPIO1, MXC_GPIO2, MXC_GPIO3}; + +int32_t gpio_init(uint32_t port) { + return MXC_GPIO_Init(port); +} diff --git a/ports/analog/peripherals/max32650/gpios.h b/ports/analog/peripherals/max32650/gpios.h index 65bac51e444..729e3a9d6da 100644 --- a/ports/analog/peripherals/max32650/gpios.h +++ b/ports/analog/peripherals/max32650/gpios.h @@ -13,3 +13,5 @@ #include "gpio.h" #include "gpio_regs.h" #include "max32650.h" + +int32_t gpio_init(uint32_t port); diff --git a/ports/analog/peripherals/max32665/gpios.c b/ports/analog/peripherals/max32665/gpios.c index 387c438e851..9a0584950f3 100644 --- a/ports/analog/peripherals/max32665/gpios.c +++ b/ports/analog/peripherals/max32665/gpios.c @@ -8,3 +8,7 @@ volatile mxc_gpio_regs_t *gpio_ports[NUM_GPIO_PORTS] = {MXC_GPIO0, MXC_GPIO1}; + +int32_t gpio_init(uint32_t port) { + return MXC_GPIO_Init(1 << port); +} diff --git a/ports/analog/peripherals/max32665/gpios.h b/ports/analog/peripherals/max32665/gpios.h index 30bd32f1407..773b4cc6809 100644 --- a/ports/analog/peripherals/max32665/gpios.h +++ b/ports/analog/peripherals/max32665/gpios.h @@ -13,3 +13,5 @@ #include "gpio.h" #include "gpio_regs.h" #include "max32665.h" + +int32_t gpio_init(uint32_t portmask); diff --git a/ports/analog/peripherals/max32690/gpios.c b/ports/analog/peripherals/max32690/gpios.c index d0dd3ad0fc1..54af8090ebf 100644 --- a/ports/analog/peripherals/max32690/gpios.c +++ b/ports/analog/peripherals/max32690/gpios.c @@ -8,3 +8,7 @@ volatile mxc_gpio_regs_t *gpio_ports[NUM_GPIO_PORTS] = {MXC_GPIO0, MXC_GPIO1, MXC_GPIO2, MXC_GPIO3, MXC_GPIO4}; + +int32_t gpio_init(uint32_t port) { + return MXC_GPIO_Init(1 << port); +} diff --git a/ports/analog/peripherals/max32690/gpios.h b/ports/analog/peripherals/max32690/gpios.h index fe912277282..9dbe5e764a2 100644 --- a/ports/analog/peripherals/max32690/gpios.h +++ b/ports/analog/peripherals/max32690/gpios.h @@ -13,3 +13,5 @@ #include "gpio.h" #include "gpio_regs.h" #include "max32690.h" + +int32_t gpio_init(uint32_t portmask); diff --git a/ports/analog/supervisor/port.c b/ports/analog/supervisor/port.c index 0888605a723..229805aa2a2 100644 --- a/ports/analog/supervisor/port.c +++ b/ports/analog/supervisor/port.c @@ -124,7 +124,7 @@ safe_mode_t port_init(void) { // Enable GPIO (enables clocks + common init for ports) for (int i = 0; i < MXC_CFG_GPIO_INSTANCES; i++) { - err = MXC_GPIO_Init(0x1 << i); + err = gpio_init(i); if (err) { return SAFE_MODE_PROGRAMMATIC; } @@ -282,7 +282,7 @@ void port_disable_tick(void) { void port_interrupt_after_ticks(uint32_t ticks) { uint32_t ticks_msec = 0; - ticks_msec = (ticks / TICKS_PER_SEC) * 1000; + ticks_msec = ((ticks * 1000) / TICKS_PER_SEC); // Disable RTC interrupts MXC_RTC_DisableInt(SSEC_ENABLE | TOD_ENABLE | RDY_ENABLE); From 53699736dfe3d210d1f227c99c30820791e16e2e Mon Sep 17 00:00:00 2001 From: Brandon-Hurst Date: Sun, 18 Jan 2026 19:00:50 -0800 Subject: [PATCH 17/23] ports: analog: Improve portability for BUSIO.UART - Move Init & Flow Control into wrapper functions in peripherals/ - Unify API differences (e.g. AsyncHandler doesn't always return an err) - Create UART register macro for TX_BUSY checking in peripherals/ Signed-off-by: Brandon-Hurst --- ports/analog/common-hal/busio/UART.c | 14 +++++--------- ports/analog/peripherals/max32650/max32_uart.c | 9 +++++++++ ports/analog/peripherals/max32650/max32_uart.h | 7 +++++++ ports/analog/peripherals/max32665/max32_uart.c | 11 ++++++++++- ports/analog/peripherals/max32665/max32_uart.h | 7 +++++++ ports/analog/peripherals/max32690/max32_uart.c | 9 +++++++++ ports/analog/peripherals/max32690/max32_uart.h | 7 +++++++ 7 files changed, 54 insertions(+), 10 deletions(-) diff --git a/ports/analog/common-hal/busio/UART.c b/ports/analog/common-hal/busio/UART.c index be7851f52a2..d95ce3f4c53 100644 --- a/ports/analog/common-hal/busio/UART.c +++ b/ports/analog/common-hal/busio/UART.c @@ -182,7 +182,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, } if ((rx != NULL) && (tx != NULL)) { - err = MXC_UART_Init(self->uart_regs, baudrate, MXC_UART_IBRO_CLK); + err = uart_init(self->uart_regs, baudrate); if (err != E_NO_ERROR) { mp_raise_RuntimeError_varg(MP_ERROR_TEXT("%q init failed"), MP_QSTR_UART); } @@ -197,7 +197,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, } if ((cts) && (rts)) { - MXC_UART_SetFlowCtrl(self->uart_regs, MXC_UART_FLOW_EN, 8); + uart_set_flow_ctrl(self->uart_regs, true, 8); self->cts_pin = cts; self->rts_pin = rts; common_hal_mcu_pin_claim(self->cts_pin); @@ -377,7 +377,7 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, uart_wr_req.rxCnt = 0; uart_wr_req.txCnt = 0; uart_wr_req.rxData = NULL; - uart_wr_req.txData = data; + uart_wr_req.txData = (uint8_t *)data; uart_wr_req.txLen = bytes_remaining; uart_wr_req.rxLen = 0; uart_wr_req.uart = self->uart_regs; @@ -394,11 +394,7 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, // Wait for transaction completion while (uart_status[self->uart_id] != UART_FREE) { - // Call the handler and abort if errors - uart_err = MXC_UART_AsyncHandler(self->uart_regs); - if (uart_err != E_NO_ERROR) { - MXC_UART_AbortAsync(self->uart_regs); - } + MXC_UART_AsyncHandler(self->uart_regs); } // Check for errors from the callback if (uart_err != E_NO_ERROR) { @@ -446,7 +442,7 @@ void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) { } bool common_hal_busio_uart_ready_to_tx(busio_uart_obj_t *self) { - return !(MXC_UART_GetStatus(self->uart_regs) & (MXC_F_UART_STATUS_TX_BUSY)); + return !(MXC_UART_GetStatus(self->uart_regs) & (UART_F_STATUS_TX_BUSY)); } void common_hal_busio_uart_never_reset(busio_uart_obj_t *self) { diff --git a/ports/analog/peripherals/max32650/max32_uart.c b/ports/analog/peripherals/max32650/max32_uart.c index a6ebcc8033f..db524bb552b 100644 --- a/ports/analog/peripherals/max32650/max32_uart.c +++ b/ports/analog/peripherals/max32650/max32_uart.c @@ -32,3 +32,12 @@ int pinsToUart(const mcu_pin_obj_t *rx, const mcu_pin_obj_t *tx) { mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_pins); return -1; } + +int uart_init(mxc_uart_regs_t *uart, unsigned int baud) { + return MXC_UART_Init(uart, baud); +} + +int uart_set_flow_ctrl(mxc_uart_regs_t *uart, bool enable, int rtsThreshold) { + mxc_uart_flow_t flow = enable ? MXC_UART_FLOW_EN_LOW : MXC_UART_FLOW_DIS; + return MXC_UART_SetFlowCtrl(uart, flow, rtsThreshold); +} diff --git a/ports/analog/peripherals/max32650/max32_uart.h b/ports/analog/peripherals/max32650/max32_uart.h index c6a81925b5b..0882e0af5c4 100644 --- a/ports/analog/peripherals/max32650/max32_uart.h +++ b/ports/analog/peripherals/max32650/max32_uart.h @@ -13,4 +13,11 @@ #define NUM_UARTS 3 +// UART register compatibility macro +#define UART_F_STATUS_TX_BUSY MXC_F_UART_STAT_TX_BUSY + int pinsToUart(const mcu_pin_obj_t *rx, const mcu_pin_obj_t *tx); + +// UART wrappers for portability +int uart_init(mxc_uart_regs_t *uart, unsigned int baud); +int uart_set_flow_ctrl(mxc_uart_regs_t *uart, bool enable, int rtsThreshold); diff --git a/ports/analog/peripherals/max32665/max32_uart.c b/ports/analog/peripherals/max32665/max32_uart.c index b89b6405811..a3c7f940ef8 100644 --- a/ports/analog/peripherals/max32665/max32_uart.c +++ b/ports/analog/peripherals/max32665/max32_uart.c @@ -13,7 +13,7 @@ #include "py/runtime.h" #include "py/mperrno.h" -// Assuming the use of MAP_A in MSDK, since all documentation +// Assuming the use of MAP_A in MSDK, since all documentation // states the GPIO maps are the same const mxc_gpio_cfg_t uart_maps[NUM_UARTS] = { @@ -38,3 +38,12 @@ int pinsToUart(const mcu_pin_obj_t *rx, const mcu_pin_obj_t *tx) { mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_pins); return -1; } + +int uart_init(mxc_uart_regs_t *uart, unsigned int baud) { + return MXC_UART_Init(uart, baud, MAP_A); +} + +int uart_set_flow_ctrl(mxc_uart_regs_t *uart, bool enable, int rtsThreshold) { + mxc_uart_flow_t flow = enable ? MXC_UART_FLOW_EN_LOW : MXC_UART_FLOW_DIS; + return MXC_UART_SetFlowCtrl(uart, flow, rtsThreshold, MAP_A); +} diff --git a/ports/analog/peripherals/max32665/max32_uart.h b/ports/analog/peripherals/max32665/max32_uart.h index c6a81925b5b..6c6dda0348c 100644 --- a/ports/analog/peripherals/max32665/max32_uart.h +++ b/ports/analog/peripherals/max32665/max32_uart.h @@ -13,4 +13,11 @@ #define NUM_UARTS 3 +// UART register compatibility macro +#define UART_F_STATUS_TX_BUSY MXC_F_UART_STATUS_TX_BUSY + int pinsToUart(const mcu_pin_obj_t *rx, const mcu_pin_obj_t *tx); + +// UART wrappers for portability +int uart_init(mxc_uart_regs_t *uart, unsigned int baud); +int uart_set_flow_ctrl(mxc_uart_regs_t *uart, bool enable, int rtsThreshold); diff --git a/ports/analog/peripherals/max32690/max32_uart.c b/ports/analog/peripherals/max32690/max32_uart.c index 7d377087974..8e9f433db5b 100644 --- a/ports/analog/peripherals/max32690/max32_uart.c +++ b/ports/analog/peripherals/max32690/max32_uart.c @@ -34,3 +34,12 @@ int pinsToUart(const mcu_pin_obj_t *rx, const mcu_pin_obj_t *tx) { mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_pins); return -1; } + +int uart_init(mxc_uart_regs_t *uart, unsigned int baud) { + return MXC_UART_Init(uart, baud, MXC_UART_IBRO_CLK); +} + +int uart_set_flow_ctrl(mxc_uart_regs_t *uart, bool enable, int rtsThreshold) { + mxc_uart_flow_t flow = enable ? MXC_UART_FLOW_EN : MXC_UART_FLOW_DIS; + return MXC_UART_SetFlowCtrl(uart, flow, rtsThreshold); +} diff --git a/ports/analog/peripherals/max32690/max32_uart.h b/ports/analog/peripherals/max32690/max32_uart.h index f03b500a3c5..3bfca7be7e9 100644 --- a/ports/analog/peripherals/max32690/max32_uart.h +++ b/ports/analog/peripherals/max32690/max32_uart.h @@ -13,4 +13,11 @@ #define NUM_UARTS 4 +// UART register compatibility macro +#define UART_F_STATUS_TX_BUSY MXC_F_UART_STATUS_TX_BUSY + int pinsToUart(const mcu_pin_obj_t *rx, const mcu_pin_obj_t *tx); + +// UART Wrappers for compatibility +int uart_init(mxc_uart_regs_t *uart, unsigned int baud); +int uart_set_flow_ctrl(mxc_uart_regs_t *uart, bool enable, int rtsThreshold); From 43a55a01a78d0538e2ad7de2aa170442cf7deddf Mon Sep 17 00:00:00 2001 From: Brandon-Hurst Date: Sun, 18 Jan 2026 19:04:51 -0800 Subject: [PATCH 18/23] ports: analog: Improve portability for BUSIO.I2C Use register wrapper macros to improve portability for I2C. This includes macros for the CTRL, STATUS, INTFL0, and FIFO registers. Additionally, some field values for MST_MODE, BUSY, ACK, and NACK are used. Signed-off-by: Brandon-Hurst --- ports/analog/common-hal/busio/I2C.c | 16 ++++++++-------- ports/analog/peripherals/max32650/max32_i2c.h | 11 +++++++++++ ports/analog/peripherals/max32665/max32_i2c.h | 11 +++++++++++ ports/analog/peripherals/max32690/max32_i2c.h | 11 +++++++++++ 4 files changed, 41 insertions(+), 8 deletions(-) diff --git a/ports/analog/common-hal/busio/I2C.c b/ports/analog/common-hal/busio/I2C.c index 7ebe721b3f4..a13a7cf986b 100644 --- a/ports/analog/common-hal/busio/I2C.c +++ b/ports/analog/common-hal/busio/I2C.c @@ -124,7 +124,7 @@ bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) { bool ret = 0; // If not in Master mode, error out (can happen in some error conditions) - if (!(self->i2c_regs->ctrl & MXC_F_I2C_CTRL_MST_MODE)) { + if (!(I2C_CTRL_REG(self->i2c_regs) & I2C_F_CTRL_MST_MODE)) { return false; } @@ -135,29 +135,29 @@ bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) { // Pre-load target address into transmit FIFO addr = (addr << 1); - self->i2c_regs->fifo = addr; + I2C_FIFO_REG(self->i2c_regs) = addr; // Set start bit & wait for it to clear MXC_I2C_Start(self->i2c_regs); // wait for ACK/NACK - while (!(self->i2c_regs->intfl0 & MXC_F_I2C_INTFL0_ADDR_ACK) && - !(self->i2c_regs->intfl0 & MXC_F_I2C_INTFL0_ADDR_NACK_ERR)) { + while (!(I2C_INTFL0_REG(self->i2c_regs) & I2C_F_INTFL0_ADDR_ACK) && + !(I2C_INTFL0_REG(self->i2c_regs) & I2C_F_INTFL0_ADDR_NACK_ERR)) { } // Save interrupt flags for ACK/NACK checking - int_fl0 = self->i2c_regs->intfl0; + int_fl0 = I2C_INTFL0_REG(self->i2c_regs); // Set / Wait for stop MXC_I2C_Stop(self->i2c_regs); // Wait for controller not busy, then clear flags - while (self->i2c_regs->status & MXC_F_I2C_STATUS_BUSY) { + while (I2C_STATUS_REG(self->i2c_regs) & I2C_F_STATUS_BUSY) { ; } MXC_I2C_ClearFlags(self->i2c_regs, 0xFFFFFF, 0xFFFFFF); - if (int_fl0 & MXC_F_I2C_INTFL0_ADDR_ACK) { + if (int_fl0 & I2C_F_INTFL0_ADDR_ACK) { ret = true; } else { ret = false; @@ -168,7 +168,7 @@ bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) { // Lock I2C bus bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self) { - if (self->i2c_regs->status & MXC_F_I2C_STATUS_BUSY) { + if (I2C_STATUS_REG(self->i2c_regs) & I2C_F_STATUS_BUSY) { return false; } else { self->has_lock = true; diff --git a/ports/analog/peripherals/max32650/max32_i2c.h b/ports/analog/peripherals/max32650/max32_i2c.h index 3e554da5abc..db6b2e719d3 100644 --- a/ports/analog/peripherals/max32650/max32_i2c.h +++ b/ports/analog/peripherals/max32650/max32_i2c.h @@ -13,4 +13,15 @@ #define NUM_I2C 2 +// I2C register compatibility macros for MAX32650 +#define I2C_CTRL_REG(i2c) ((i2c)->ctrl0) +#define I2C_STATUS_REG(i2c) ((i2c)->stat) +#define I2C_INTFL0_REG(i2c) ((i2c)->int_fl0) +#define I2C_FIFO_REG(i2c) ((i2c)->fifo) + +#define I2C_F_CTRL_MST_MODE MXC_F_I2C_CTRL0_MST +#define I2C_F_STATUS_BUSY MXC_F_I2C_STAT_BUSY +#define I2C_F_INTFL0_ADDR_ACK MXC_F_I2C_INT_FL0_ADRACKI +#define I2C_F_INTFL0_ADDR_NACK_ERR MXC_F_I2C_INT_FL0_ADRERI + int pinsToI2c(const mcu_pin_obj_t *sda, const mcu_pin_obj_t *scl); diff --git a/ports/analog/peripherals/max32665/max32_i2c.h b/ports/analog/peripherals/max32665/max32_i2c.h index b64cfd308dc..cc5c7e27db1 100644 --- a/ports/analog/peripherals/max32665/max32_i2c.h +++ b/ports/analog/peripherals/max32665/max32_i2c.h @@ -13,4 +13,15 @@ #define NUM_I2C 3 +// I2C register compatibility macros for MAX32665 +#define I2C_CTRL_REG(i2c) ((i2c)->ctrl) +#define I2C_STATUS_REG(i2c) ((i2c)->status) +#define I2C_INTFL0_REG(i2c) ((i2c)->int_fl0) +#define I2C_FIFO_REG(i2c) ((i2c)->fifo) + +#define I2C_F_CTRL_MST_MODE MXC_F_I2C_CTRL_MST +#define I2C_F_STATUS_BUSY MXC_F_I2C_STATUS_BUS +#define I2C_F_INTFL0_ADDR_ACK MXC_F_I2C_INT_FL0_ADDR_ACK +#define I2C_F_INTFL0_ADDR_NACK_ERR MXC_F_I2C_INT_FL0_ADDR_NACK_ER + int pinsToI2c(const mcu_pin_obj_t *sda, const mcu_pin_obj_t *scl); diff --git a/ports/analog/peripherals/max32690/max32_i2c.h b/ports/analog/peripherals/max32690/max32_i2c.h index b64cfd308dc..469b02e5969 100644 --- a/ports/analog/peripherals/max32690/max32_i2c.h +++ b/ports/analog/peripherals/max32690/max32_i2c.h @@ -13,4 +13,15 @@ #define NUM_I2C 3 +// I2C register compatibility macros for MAX32690 +#define I2C_CTRL_REG(i2c) ((i2c)->ctrl) +#define I2C_STATUS_REG(i2c) ((i2c)->status) +#define I2C_INTFL0_REG(i2c) ((i2c)->intfl0) +#define I2C_FIFO_REG(i2c) ((i2c)->fifo) + +#define I2C_F_CTRL_MST_MODE MXC_F_I2C_CTRL_MST_MODE +#define I2C_F_STATUS_BUSY MXC_F_I2C_STATUS_BUSY +#define I2C_F_INTFL0_ADDR_ACK MXC_F_I2C_INTFL0_ADDR_ACK +#define I2C_F_INTFL0_ADDR_NACK_ERR MXC_F_I2C_INTFL0_ADDR_NACK_ERR + int pinsToI2c(const mcu_pin_obj_t *sda, const mcu_pin_obj_t *scl); From 5707ae2fc6f3a121251b2c4e4459e90a71dcd0e0 Mon Sep 17 00:00:00 2001 From: Brandon-Hurst Date: Sun, 18 Jan 2026 19:13:48 -0800 Subject: [PATCH 19/23] ports: analog: Improve portability for BUSIO.SPI - Unify initialization into spi_init function in peripherals - Use mxc_spi_mode_t to unify SPI mode handling across MSDK APIs - Set default TX data with MXC_SPI_SetDefaultTXData to account for different mxc_spi_req_t structures across parts. - Implement spi_init for MAX32690/MAX32650/MAX32665 Signed-off-by: Brandon-Hurst --- ports/analog/common-hal/busio/SPI.c | 42 +++++++------------ ports/analog/peripherals/max32650/max32_spi.c | 5 +++ ports/analog/peripherals/max32650/max32_spi.h | 3 ++ ports/analog/peripherals/max32665/max32_spi.c | 6 +++ ports/analog/peripherals/max32665/max32_spi.h | 3 ++ ports/analog/peripherals/max32690/max32_spi.c | 15 +++++++ ports/analog/peripherals/max32690/max32_spi.h | 3 ++ 7 files changed, 50 insertions(+), 27 deletions(-) diff --git a/ports/analog/common-hal/busio/SPI.c b/ports/analog/common-hal/busio/SPI.c index bdbe6da9d94..f6a09e20612 100644 --- a/ports/analog/common-hal/busio/SPI.c +++ b/ports/analog/common-hal/busio/SPI.c @@ -32,7 +32,6 @@ #include "shared-bindings/microcontroller/Pin.h" #include "max32_port.h" -#include "spi_reva1.h" // Note that any bugs introduced in this file can cause crashes // at startupfor chips using external SPI flash. @@ -72,25 +71,11 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, self->spi_regs = MXC_SPI_GET_SPI(spi_id); } - // Other pins default to true - mxc_spi_pins_t spi_pins = { - .clock = TRUE, - .mosi = TRUE, - .miso = TRUE, - .ss0 = FALSE, - .ss1 = FALSE, - .ss2 = FALSE, - .vddioh = true, - .drvstr = MXC_GPIO_DRVSTR_0 - }; - assert((self->spi_id >= 0) && (self->spi_id < NUM_SPI)); // Init SPI controller if ((mosi != NULL) && (miso != NULL) && (sck != NULL)) { - // spi, mastermode, quadModeUsed, numSubs, ssPolarity, frequency - err = MXC_SPI_Init(self->spi_regs, MXC_SPI_TYPE_CONTROLLER, MXC_SPI_INTERFACE_STANDARD, - 1, 0x01, 1000000, spi_pins); + err = spi_init(self->spi_regs, 1000000); MXC_GPIO_SetVSSEL(MXC_GPIO_GET_GPIO(sck->port), MXC_GPIO_VSSEL_VDDIOH, (sck->mask | miso->mask | mosi->mask | MXC_GPIO_PIN_0)); if (err) { // NOTE: Reuse existing messages from locales/circuitpython.pot to save space @@ -154,7 +139,7 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self, uint8_t phase, uint8_t bits) { - mxc_spi_clkmode_t clk_mode; + mxc_spi_mode_t spi_mode; int ret; self->polarity = polarity; @@ -163,16 +148,16 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self, switch ((polarity << 1) | (phase)) { case 0b00: - clk_mode = MXC_SPI_CLKMODE_0; + spi_mode = SPI_MODE_0; break; case 0b01: - clk_mode = MXC_SPI_CLKMODE_1; + spi_mode = SPI_MODE_1; break; case 0b10: - clk_mode = MXC_SPI_CLKMODE_2; + spi_mode = SPI_MODE_2; break; case 0b11: - clk_mode = MXC_SPI_CLKMODE_3; + spi_mode = SPI_MODE_3; break; default: // should not be reachable; validated in shared-bindings/busio/SPI.c @@ -214,7 +199,7 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self, } else if (ret == E_BAD_STATE) { mp_raise_RuntimeError(MP_ERROR_TEXT("Invalid state")); } - ret = MXC_SPI_SetMode(self->spi_regs, clk_mode); + ret = MXC_SPI_SetMode(self->spi_regs, spi_mode); if (ret) { mp_raise_ValueError(MP_ERROR_TEXT("Failed to set SPI Clock Mode")); return false; @@ -248,6 +233,8 @@ bool common_hal_busio_spi_write(busio_spi_obj_t *self, size_t len) { int ret = 0; + MXC_SPI_SetDefaultTXData(self->spi_regs, 0xFF); + mxc_spi_req_t wr_req = { .spi = self->spi_regs, .ssIdx = 0, @@ -259,7 +246,6 @@ bool common_hal_busio_spi_write(busio_spi_obj_t *self, .rxLen = 0, .ssDeassert = 1, .completeCB = NULL, - .txDummyValue = 0xFF, }; ret = MXC_SPI_MasterTransaction(&wr_req); if (ret) { @@ -276,6 +262,8 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self, int ret = 0; + MXC_SPI_SetDefaultTXData(self->spi_regs, write_value); + mxc_spi_req_t rd_req = { .spi = self->spi_regs, .ssIdx = 0, @@ -287,7 +275,6 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self, .rxLen = len, .ssDeassert = 1, .completeCB = NULL, - .txDummyValue = write_value, }; ret = MXC_SPI_MasterTransaction(&rd_req); if (ret) { @@ -306,7 +293,9 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, int ret = 0; - mxc_spi_req_t rd_req = { + MXC_SPI_SetDefaultTXData(self->spi_regs, 0xFF); + + mxc_spi_req_t transfer_req = { .spi = self->spi_regs, .ssIdx = 0, .txCnt = 0, @@ -317,9 +306,8 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, .rxLen = len, .ssDeassert = 1, .completeCB = NULL, - .txDummyValue = 0xFF, }; - ret = MXC_SPI_MasterTransaction(&rd_req); + ret = MXC_SPI_MasterTransaction(&transfer_req); if (ret) { return false; } else { diff --git a/ports/analog/peripherals/max32650/max32_spi.c b/ports/analog/peripherals/max32650/max32_spi.c index 8c97c486b67..24546d31ee4 100644 --- a/ports/analog/peripherals/max32650/max32_spi.c +++ b/ports/analog/peripherals/max32650/max32_spi.c @@ -40,3 +40,8 @@ int pinsToSpi(const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_pins); return -1; } + +int spi_init(mxc_spi_regs_t *spi, unsigned int freq) { + // masterMode=1, quadModeUsed=0, numSlaves=1, ssPolarity=0x01 + return MXC_SPI_Init(spi, 1, 0, 1, 0x01, freq); +} diff --git a/ports/analog/peripherals/max32650/max32_spi.h b/ports/analog/peripherals/max32650/max32_spi.h index c4f6e8062f1..faf37cfb32e 100644 --- a/ports/analog/peripherals/max32650/max32_spi.h +++ b/ports/analog/peripherals/max32650/max32_spi.h @@ -16,3 +16,6 @@ int pinsToSpi(const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, const mcu_pin_obj_t *sck); + +// SPI Init wrapper +int spi_init(mxc_spi_regs_t *spi, unsigned int freq); diff --git a/ports/analog/peripherals/max32665/max32_spi.c b/ports/analog/peripherals/max32665/max32_spi.c index 993a8d7f52e..275b344c5b6 100644 --- a/ports/analog/peripherals/max32665/max32_spi.c +++ b/ports/analog/peripherals/max32665/max32_spi.c @@ -9,6 +9,7 @@ #include "common-hal/busio/SPI.h" #include "max32_spi.h" #include "max32665.h" +#include "mxc_pins.h" #include "py/runtime.h" #include "py/mperrno.h" @@ -43,3 +44,8 @@ int pinsToSpi(const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_pins); return -1; } + +int spi_init(mxc_spi_regs_t *spi, unsigned int freq) { + // masterMode=1, quadModeUsed=0, numSlaves=1, ssPolarity=0x01, map=MAP_A + return MXC_SPI_Init(spi, 1, 0, 1, 0x01, freq, MAP_A); +} diff --git a/ports/analog/peripherals/max32665/max32_spi.h b/ports/analog/peripherals/max32665/max32_spi.h index 54e51a1d6a0..d1e68b524e6 100644 --- a/ports/analog/peripherals/max32665/max32_spi.h +++ b/ports/analog/peripherals/max32665/max32_spi.h @@ -15,3 +15,6 @@ int pinsToSpi(const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, const mcu_pin_obj_t *sck); + +// SPI Init wrapper +int spi_init(mxc_spi_regs_t *spi, unsigned int freq); diff --git a/ports/analog/peripherals/max32690/max32_spi.c b/ports/analog/peripherals/max32690/max32_spi.c index c78fd64dbd7..fddca47fe05 100644 --- a/ports/analog/peripherals/max32690/max32_spi.c +++ b/ports/analog/peripherals/max32690/max32_spi.c @@ -42,3 +42,18 @@ int pinsToSpi(const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_pins); return -1; } + +int spi_init(mxc_spi_regs_t *spi, unsigned int freq) { + mxc_spi_pins_t spi_pins = { + .clock = true, + .mosi = true, + .miso = true, + .ss0 = false, + .ss1 = false, + .ss2 = false, + .vddioh = true, + .drvstr = MXC_GPIO_DRVSTR_0 + }; + return MXC_SPI_Init(spi, MXC_SPI_TYPE_CONTROLLER, MXC_SPI_INTERFACE_STANDARD, + 1, 0x01, freq, spi_pins); +} diff --git a/ports/analog/peripherals/max32690/max32_spi.h b/ports/analog/peripherals/max32690/max32_spi.h index 76bb48a59a7..fe2a8562069 100644 --- a/ports/analog/peripherals/max32690/max32_spi.h +++ b/ports/analog/peripherals/max32690/max32_spi.h @@ -15,3 +15,6 @@ int pinsToSpi(const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, const mcu_pin_obj_t *sck); + +// SPI Init wrapper +int spi_init(mxc_spi_regs_t *spi, unsigned int freq); From 75385fb69227e7f2a1f54e24f32cd3b1934c234c Mon Sep 17 00:00:00 2001 From: Brandon-Hurst Date: Fri, 23 Jan 2026 11:49:15 -0800 Subject: [PATCH 20/23] ports: analog: Update makefile for latest MSDK - Unify common PeriphDriver files outside of MCU-specific .mk files. - Add warning suppression for "set-but-unused" to accommodate DMA driver update Signed-off-by: Brandon-Hurst --- ports/analog/Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ports/analog/Makefile b/ports/analog/Makefile index cd6a77bc5ae..0573e8242e2 100644 --- a/ports/analog/Makefile +++ b/ports/analog/Makefile @@ -76,6 +76,10 @@ endif # MSDK Specific Includes / Sources MXC_SPI_VERSION := v1 +PERIPH_DRIVER_C_FILES += $(SOURCE_DIR)/SYS/mxc_assert.c +PERIPH_DRIVER_C_FILES += $(SOURCE_DIR)/SYS/mxc_delay.c +PERIPH_DRIVER_C_FILES += $(SOURCE_DIR)/SYS/nvic_table.c +PERIPH_DRIVER_C_FILES += $(SOURCE_DIR)/SYS/mxc_lock.c include ./msdk/Libraries/PeriphDrivers/${MCU_VARIANT_LOWER}_files.mk # Add MAX32 files to Include / Source paths @@ -189,6 +193,7 @@ CFLAGS += -Wno-error=unused-parameter \ -Wno-error=strict-prototypes \ -Wno-error=cast-qual \ -Wno-error=unused-variable \ + -Wno-error=unused-but-set-variable \ -Wno-error=lto-type-mismatch \ -Wno-error=cast-align \ -Wno-error=nested-externs \ From da6ed279adecad78332fa2463404c3a7b8e7484e Mon Sep 17 00:00:00 2001 From: Brandon-Hurst Date: Fri, 23 Jan 2026 11:51:10 -0800 Subject: [PATCH 21/23] ports: analog: Update SPI peripheral helpers - Fix pinsToSpi function signature to correctly matchup pins - Pin changes for MAX32665 to match package on common Eval boards - Use '&' instead of '==' for pinmasks to allow for easier pin usage in C code (This may make it simpler to copy GPIO structs from MSDK down the line) Signed-off-by: Brandon-Hurst --- ports/analog/peripherals/max32650/max32_spi.c | 6 +++--- ports/analog/peripherals/max32665/max32_spi.c | 15 ++++++--------- ports/analog/peripherals/max32690/max32_spi.c | 6 +++--- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/ports/analog/peripherals/max32650/max32_spi.c b/ports/analog/peripherals/max32650/max32_spi.c index 24546d31ee4..c7efc16c2d8 100644 --- a/ports/analog/peripherals/max32650/max32_spi.c +++ b/ports/analog/peripherals/max32650/max32_spi.c @@ -29,11 +29,11 @@ const mxc_gpio_cfg_t spi_maps[NUM_SPI] = { MXC_GPIO_FUNC_ALT1, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, }; -int pinsToSpi(const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, - const mcu_pin_obj_t *sck) { +int pinsToSpi(const mcu_pin_obj_t *sck, const mcu_pin_obj_t *mosi, + const mcu_pin_obj_t *miso) { for (int i = 0; i < NUM_SPI; i++) { if ((spi_maps[i].port == (MXC_GPIO_GET_GPIO(mosi->port))) - && (spi_maps[i].mask == ((mosi->mask) | (miso->mask) | (sck->mask)))) { + && (spi_maps[i].mask & ((mosi->mask) | (miso->mask) | (sck->mask)))) { return i; } } diff --git a/ports/analog/peripherals/max32665/max32_spi.c b/ports/analog/peripherals/max32665/max32_spi.c index 275b344c5b6..d4a7e432c21 100644 --- a/ports/analog/peripherals/max32665/max32_spi.c +++ b/ports/analog/peripherals/max32665/max32_spi.c @@ -19,25 +19,22 @@ const mxc_gpio_cfg_t spi_maps[NUM_SPI] = { // SPI0A - { MXC_GPIO1, - (MXC_GPIO_PIN_9 | MXC_GPIO_PIN_10 | MXC_GPIO_PIN_11 | MXC_GPIO_PIN_12 | MXC_GPIO_PIN_13), + { MXC_GPIO1, (MXC_GPIO_PIN_9 | MXC_GPIO_PIN_10 | MXC_GPIO_PIN_11), MXC_GPIO_FUNC_ALT1, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, // SPI1 - { MXC_GPIO0, - (MXC_GPIO_PIN_17 | MXC_GPIO_PIN_18 | MXC_GPIO_PIN_19 | MXC_GPIO_PIN_20 | MXC_GPIO_PIN_21), + { MXC_GPIO0, (MXC_GPIO_PIN_17 | MXC_GPIO_PIN_18 | MXC_GPIO_PIN_19), MXC_GPIO_FUNC_ALT2, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, // SPI2 - { MXC_GPIO0, - (MXC_GPIO_PIN_25 | MXC_GPIO_PIN_26 | MXC_GPIO_PIN_27 | MXC_GPIO_PIN_28 | MXC_GPIO_PIN_29), + { MXC_GPIO0, (MXC_GPIO_PIN_25 | MXC_GPIO_PIN_26 | MXC_GPIO_PIN_27), MXC_GPIO_FUNC_ALT2, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, }; -int pinsToSpi(const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, - const mcu_pin_obj_t *sck) { +int pinsToSpi(const mcu_pin_obj_t *sck, const mcu_pin_obj_t *mosi, + const mcu_pin_obj_t *miso) { for (int i = 0; i < NUM_SPI; i++) { if ((spi_maps[i].port == (MXC_GPIO_GET_GPIO(mosi->port))) - && (spi_maps[i].mask == ((mosi->mask) | (miso->mask) | (sck->mask)))) { + && (spi_maps[i].mask & ((mosi->mask) | (miso->mask) | (sck->mask)))) { return i; } } diff --git a/ports/analog/peripherals/max32690/max32_spi.c b/ports/analog/peripherals/max32690/max32_spi.c index fddca47fe05..1de4fefad09 100644 --- a/ports/analog/peripherals/max32690/max32_spi.c +++ b/ports/analog/peripherals/max32690/max32_spi.c @@ -31,11 +31,11 @@ const mxc_gpio_cfg_t spi_maps[NUM_SPI] = { MXC_GPIO_FUNC_ALT1, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, }; -int pinsToSpi(const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, - const mcu_pin_obj_t *sck) { +int pinsToSpi(const mcu_pin_obj_t *sck, const mcu_pin_obj_t *mosi, + const mcu_pin_obj_t *miso) { for (int i = 0; i < NUM_SPI; i++) { if ((spi_maps[i].port == (MXC_GPIO_GET_GPIO(mosi->port))) - && (spi_maps[i].mask == ((mosi->mask) | (miso->mask) | (sck->mask)))) { + && (spi_maps[i].mask & ((mosi->mask) | (miso->mask) | (sck->mask)))) { return i; } } From b51ab780911c63714a25ae89b2948c8773b73814 Mon Sep 17 00:00:00 2001 From: Brandon-Hurst Date: Fri, 23 Jan 2026 11:53:07 -0800 Subject: [PATCH 22/23] ports: analog: Update common-hal to align pinsToSpi function signature Signed-off-by: Brandon-Hurst --- ports/analog/common-hal/busio/SPI.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/analog/common-hal/busio/SPI.c b/ports/analog/common-hal/busio/SPI.c index f6a09e20612..d4ac03e7c0e 100644 --- a/ports/analog/common-hal/busio/SPI.c +++ b/ports/analog/common-hal/busio/SPI.c @@ -63,7 +63,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, common_hal_busio_spi_mark_deinit(self); // Assign SPI ID based on pins - int spi_id = pinsToSpi(mosi, miso, sck); + int spi_id = pinsToSpi(sck, mosi, miso); if (spi_id == -1) { return; } else { From 063a170be716f3f49e16014c6cc352e0e06ff908 Mon Sep 17 00:00:00 2001 From: Brandon Hurst Date: Mon, 7 Sep 2026 15:53:37 -0700 Subject: [PATCH 23/23] ports: analog: remove unused/redundant FLASH region from linkerscripts Signed-off-by: Brandon Hurst --- ports/analog/linking/max32650_cktpy.ld | 7 +++---- ports/analog/linking/max32665_cktpy.ld | 1 - ports/analog/linking/max32690_cktpy.ld | 7 ++++--- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/ports/analog/linking/max32650_cktpy.ld b/ports/analog/linking/max32650_cktpy.ld index 3e72798f1dc..64ea7307bfa 100644 --- a/ports/analog/linking/max32650_cktpy.ld +++ b/ports/analog/linking/max32650_cktpy.ld @@ -5,15 +5,14 @@ * SPDX-License-Identifier: MIT */ -/* +/* * FLASH_FIRMWARE: 3072 KiB - 128 KiB = 2944 KiB - * - * Start & Size for FLASH_FIRMWARE and RAM MUST be raw numbers + * + * Start & Size for FLASH_FIRMWARE and RAM MUST be raw numbers * b/c FLASH_FIMRWARE is parsed with Python build_memory_info.py */ MEMORY { ROM (rx) : ORIGIN = 0x00000000, LENGTH = 128K - FLASH (rx) : ORIGIN = 0x10000000, LENGTH = 3M FLASH_FIRMWARE (rx) : ORIGIN = 0x10000000, LENGTH = 2944K FLASH_FS (rx) : ORIGIN = 0x102E0000, LENGTH = 128K RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 1M diff --git a/ports/analog/linking/max32665_cktpy.ld b/ports/analog/linking/max32665_cktpy.ld index fe0e2a9df74..c7a5d5d2bbd 100644 --- a/ports/analog/linking/max32665_cktpy.ld +++ b/ports/analog/linking/max32665_cktpy.ld @@ -13,7 +13,6 @@ */ MEMORY { ROM (rx) : ORIGIN = 0x00000000, LENGTH = 128K - FLASH (rx) : ORIGIN = 0x10000000, LENGTH = 1M FLASH_FIRMWARE (rx) : ORIGIN = 0x10000000, LENGTH = 896K FLASH_FS (rx) : ORIGIN = 0x100E0000, LENGTH = 128K RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 560K diff --git a/ports/analog/linking/max32690_cktpy.ld b/ports/analog/linking/max32690_cktpy.ld index 4aac33fef9c..18cd6e7e713 100644 --- a/ports/analog/linking/max32690_cktpy.ld +++ b/ports/analog/linking/max32690_cktpy.ld @@ -5,10 +5,10 @@ * SPDX-License-Identifier: MIT */ -/* +/* * FLASH_FIRMWARE: 3072 KiB - 128 KiB = 2944 KiB - * - * Start & Size for FLASH_FIRMWARE and RAM MUST be raw numbers + * + * Start & Size for FLASH_FIRMWARE and RAM MUST be raw numbers * b/c FLASH_FIMRWARE is parsed with Python build_memory_info.py */ MEMORY { @@ -17,6 +17,7 @@ MEMORY { FLASH_FS (rx) : ORIGIN = 0x102E0000, LENGTH = 128K RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 1M } +/* FLASH FIRMWARE: 3072K [3MB] - 128K = 2944K */ SECTIONS { .rom :