Skip to content

Commit 9659673

Browse files
authored
Merge pull request #9667 from Brandon-Hurst/port/max32690
Add support for ADI MAX32690 microcontroller
2 parents 67a818b + 24b53f5 commit 9659673

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+3406
-1
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,3 +407,6 @@
407407
[submodule "frozen/Adafruit_CircuitPython_Wiznet5k"]
408408
path = frozen/Adafruit_CircuitPython_Wiznet5k
409409
url = https://github.com/adafruit/Adafruit_CircuitPython_Wiznet5k
410+
[submodule "ports/analog/msdk"]
411+
path = ports/analog/msdk
412+
url = https://github.com/analogdevicesinc/msdk.git

docs/shared_bindings_matrix.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
from concurrent.futures import ThreadPoolExecutor
3232

3333
SUPPORTED_PORTS = [
34+
"analog",
3435
"atmel-samd",
3536
"broadcom",
3637
"cxd56",

docs/supported_ports.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Additional testing is limited.
1212
.. toctree::
1313
:maxdepth: 2
1414

15+
../ports/analog/README
1516
../ports/atmel-samd/README
1617
../ports/broadcom/README
1718
../ports/cxd56/README

ports/analog/Makefile

Lines changed: 304 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,304 @@
1+
# This file is part of the CircuitPython project: https://circuitpython.org
2+
#
3+
# SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
4+
# SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc.
5+
#
6+
# SPDX-License-Identifier: MIT
7+
8+
# Includes mpconfigboard.mk & mpconfigport.mk,
9+
# along with numerous other shared environment makefiles.
10+
include ../../py/circuitpy_mkenv.mk
11+
12+
CROSS_COMPILE = arm-none-eabi-
13+
14+
# MCU_SERIES e.g. "max32"
15+
# MCU_VARIANT e.g. "max32690"
16+
# defined in mpconfigboard.mk
17+
MCU_SERIES_LOWER := $(shell echo $(MCU_SERIES) | tr '[:upper:]' '[:lower:]')
18+
MCU_SERIES_UPPER := $(shell echo $(MCU_SERIES) | tr '[:lower:]' '[:upper:]')
19+
MCU_VARIANT_LOWER := $(shell echo $(MCU_VARIANT) | tr '[:upper:]' '[:lower:]')
20+
MCU_VARIANT_UPPER := $(shell echo $(MCU_VARIANT) | tr '[:lower:]' '[:upper:]')
21+
22+
# *******************************************************************************
23+
#### MSDK INCLUDES ####
24+
# Necessary for msdk makefiles
25+
TARGET := $(MCU_VARIANT_UPPER)
26+
TARGET_UC := $(MCU_VARIANT_UPPER)
27+
TARGET_LC := $(MCU_VARIANT_LOWER)
28+
29+
MSDK_ROOT = ./msdk
30+
MSDK_LIBS = $(MSDK_ROOT)/Libraries
31+
CMSIS_ROOT = $(MSDK_LIBS)/CMSIS
32+
ADI_PERIPH = $(MSDK_ROOT)/Libraries/PeriphDrivers
33+
ADI_MISC_DRIVERS_DIR ?= $(MSDK_LIBS)/MiscDrivers
34+
ADI_BOARD_DIR = $(MSDK_LIBS)/Boards/$(MCU_VARIANT_UPPER)/$(BOARD)
35+
36+
# For debugging the build
37+
ifneq ($(BUILD_VERBOSE),"")
38+
$(info MSDK_ROOT is $(MSDK_ROOT))
39+
$(info MSDK_LIBS is $(MSDK_LIBS))
40+
$(info CMSIS_ROOT is $(CMSIS_ROOT))
41+
$(info ADI_PERIPH is $(ADI_PERIPH))
42+
$(info ADI_MISC_DRIVERS_DIR is $(ADI_MISC_DRIVERS_DIR))
43+
$(info ADI_BOARD_DIR is $(ADI_BOARD_DIR))
44+
$(info MAXIM_PATH is $(MAXIM_PATH))
45+
endif
46+
47+
# -----------------
48+
# Sources & Include
49+
# -----------------
50+
# Define max32 die type for PeriphDriver Includes
51+
# default to me18 for max32690
52+
# more info:
53+
# https://analogdevicesinc.github.io/msdk//USERGUIDE/#die-types-to-part-numbers
54+
ifeq ($(MCU_VARIANT_LOWER), "max32690")
55+
DIE_TYPE=me18
56+
else
57+
DIE_TYPE=me18
58+
endif
59+
60+
PERIPH_SRC = $(ADI_PERIPH)/Source
61+
62+
INC += -I.
63+
INC += -I../..
64+
INC += -I$(BUILD)
65+
INC += -I$(BUILD)/genhdr
66+
INC += -I./../../lib/cmsis/inc
67+
INC += -I./boards/
68+
INC += -I./boards/$(BOARD)
69+
INC += -I./peripherals/
70+
INC += -I../../lib/mp-readline
71+
72+
INC += \
73+
-I$(TOP)/$(BOARD_PATH) \
74+
-I$(TOP)/lib/cmsis/inc \
75+
-I$(CMSIS_ROOT)/Include \
76+
-I$(CMSIS_ROOT)/Device/Maxim/$(MCU_VARIANT_UPPER)/Include \
77+
-I$(ADI_PERIPH)/Include/$(MCU_VARIANT_UPPER) \
78+
-I$(PERIPH_SRC)/SYS \
79+
-I$(PERIPH_SRC)/CTB \
80+
-I$(PERIPH_SRC)/DMA \
81+
-I$(PERIPH_SRC)/FLC \
82+
-I$(PERIPH_SRC)/GPIO \
83+
-I$(PERIPH_SRC)/ICC \
84+
-I$(PERIPH_SRC)/TMR \
85+
-I$(PERIPH_SRC)/RTC \
86+
-I$(PERIPH_SRC)/UART
87+
88+
INC += -I$(CMSIS_ROOT)/Device/Maxim/$(MCU_VARIANT_UPPER)/Source/GCC
89+
90+
SRC_MAX32 += \
91+
$(CMSIS_ROOT)/Device/Maxim/$(MCU_VARIANT_UPPER)/Source/heap.c \
92+
$(CMSIS_ROOT)/Device/Maxim/$(MCU_VARIANT_UPPER)/Source/system_$(MCU_VARIANT_LOWER).c \
93+
$(PERIPH_SRC)/SYS/mxc_assert.c \
94+
$(PERIPH_SRC)/SYS/mxc_delay.c \
95+
$(PERIPH_SRC)/SYS/mxc_lock.c \
96+
$(PERIPH_SRC)/SYS/nvic_table.c \
97+
$(PERIPH_SRC)/SYS/pins_$(DIE_TYPE).c \
98+
$(PERIPH_SRC)/SYS/sys_$(DIE_TYPE).c \
99+
$(PERIPH_SRC)/CTB/ctb_$(DIE_TYPE).c \
100+
$(PERIPH_SRC)/CTB/ctb_reva.c \
101+
$(PERIPH_SRC)/CTB/ctb_common.c \
102+
$(PERIPH_SRC)/DMA/dma_reva.c \
103+
$(PERIPH_SRC)/DMA/dma_$(DIE_TYPE).c \
104+
$(PERIPH_SRC)/FLC/flc_common.c \
105+
$(PERIPH_SRC)/FLC/flc_$(DIE_TYPE).c \
106+
$(PERIPH_SRC)/FLC/flc_reva.c \
107+
$(PERIPH_SRC)/GPIO/gpio_common.c \
108+
$(PERIPH_SRC)/GPIO/gpio_$(DIE_TYPE).c \
109+
$(PERIPH_SRC)/GPIO/gpio_reva.c \
110+
$(PERIPH_SRC)/ICC/icc_$(DIE_TYPE).c \
111+
$(PERIPH_SRC)/ICC/icc_reva.c \
112+
$(PERIPH_SRC)/RTC/rtc_$(DIE_TYPE).c \
113+
$(PERIPH_SRC)/RTC/rtc_reva.c \
114+
$(PERIPH_SRC)/TMR/tmr_common.c \
115+
$(PERIPH_SRC)/TMR/tmr_revb.c \
116+
$(PERIPH_SRC)/TMR/tmr_$(DIE_TYPE).c \
117+
$(PERIPH_SRC)/UART/uart_common.c \
118+
$(PERIPH_SRC)/UART/uart_$(DIE_TYPE).c \
119+
$(PERIPH_SRC)/UART/uart_revb.c
120+
121+
SRC_C += $(SRC_MAX32) \
122+
boards/$(BOARD)/board.c \
123+
boards/$(BOARD)/pins.c \
124+
peripherals/$(MCU_VARIANT_LOWER)/pins.c \
125+
peripherals/$(MCU_VARIANT_LOWER)/gpios.c
126+
127+
# *******************************************************************************
128+
### Compiler & Linker Flags ###
129+
COMPILER ?= GCC
130+
131+
ifeq ($(COMPILER), GCC)
132+
133+
STARTUPFILE = $(CMSIS_ROOT)/Device/Maxim/$(MCU_VARIANT_UPPER)/Source/GCC/startup_$(MCU_VARIANT_LOWER).s
134+
# STARTUPFILE = $(ADI_BOARD_DIR)/Source/startup_$(MCU_VARIANT_LOWER).s
135+
136+
# CircuitPython custom linkerfile (necessary for build steps & filesystems)
137+
LINKERFILE = linking/$(MCU_VARIANT_LOWER)_cktpy.ld
138+
LDFLAGS += -nostartfiles -specs=nano.specs
139+
endif
140+
141+
SRC_S += supervisor/cpu.s \
142+
$(STARTUPFILE)
143+
144+
# Needed to compile some MAX32 headers
145+
CFLAGS += -D$(MCU_VARIANT_UPPER) \
146+
-DTARGET_REV=0x4131 \
147+
-DTARGET=$(MCU_VARIANT_UPPER) \
148+
-DIAR_PRAGMAS=0 \
149+
-DRISCV_LOAD=0 \
150+
-DCONFIG_TRUSTED_EXECUTION_SECURE=0
151+
152+
# todo: add these for linkerfiles later on so that it's easier to add new boards
153+
# -DFLASH_ORIGIN \
154+
# -DFLASH_SIZE \
155+
# -DSRAM_ORIGIN \
156+
# -DSRAM_SIZE
157+
158+
CPU_CORE=cortex-m4
159+
CFLAGS += -mthumb -mcpu=$(CPU_CORE) -mfloat-abi=softfp -mfpu=fpv4-sp-d16
160+
161+
# NOTE: Start with DEBUG=1 defaults for now
162+
ifeq ($(DEBUG),)
163+
DEBUG ?= 1
164+
endif
165+
166+
ifeq ($(DEBUG),1)
167+
COPT = -ggdb3 -Og -Os
168+
else
169+
COPT += -Os
170+
endif
171+
172+
# TinyUSB CFLAGS
173+
CFLAGS += \
174+
-DCFG_TUSB_MCU=OPT_MCU_$(MCU_VARIANT_UPPER) \
175+
-DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED \
176+
-DCFG_TUSB_OS=OPT_OS_NONE \
177+
-DCFG_TUD_CDC_TX_BUFSIZE=1024 \
178+
-DCFG_TUD_CDC_RX_BUFSIZE=1024 \
179+
-DCFG_TUD_MSC_BUFSIZE=4096 \
180+
-DCFG_TUD_MIDI_RX_BUFSIZE=128 \
181+
-DCFG_TUD_MIDI_TX_BUFSIZE=128 \
182+
-DCFG_TUD_VENDOR_RX_BUFSIZE=1024 \
183+
-DCFG_TUD_VENDOR_TX_BUFSIZE=1024
184+
185+
# Add TinyUSB sources
186+
INC += -I../../lib/tinyusb/src
187+
INC += -I../../supervisor/shared/usb
188+
SRC_C += lib/tinyusb/src/portable/mentor/musb/dcd_musb.c
189+
190+
# Add port sources incl. any board functions
191+
SRC_C += \
192+
boards/$(BOARD)/board.c \
193+
background.c \
194+
mphalport.c \
195+
196+
CFLAGS += $(INC) -Werror -Wall -std=gnu11 -nostartfiles $(BASE_CFLAGS) $(COPT)
197+
198+
# Suppress some errors for MSDK
199+
# cast-align warning will be suppressed;
200+
# it gets generated by CircuitPy's TLSF memory allocator lib
201+
CFLAGS += -Wno-error=unused-parameter \
202+
-Wno-error=old-style-declaration \
203+
-Wno-error=sign-compare \
204+
-Wno-error=strict-prototypes \
205+
-Wno-error=cast-qual \
206+
-Wno-error=unused-variable \
207+
-Wno-error=lto-type-mismatch \
208+
-Wno-error=cast-align \
209+
-Wno-error=nested-externs \
210+
-Wno-error=sign-compare \
211+
-Wno-cast-align \
212+
-Wno-sign-compare \
213+
214+
ENTRY = Reset_Handler
215+
LDFLAGS += $(CFLAGS) --entry $(ENTRY) -Wl,-nostdlib -Wl,-T,$(LINKERFILE) -Wl,-Map=$@.map -Wl,-cref -Wl,-gc-sections
216+
LIBS := -lgcc -lc
217+
218+
# If not using CKTPY mathlib, use toolchain mathlib
219+
ifndef INTERNAL_LIBM
220+
LIBS += -lm
221+
endif
222+
223+
# *******************************************************************************
224+
### PORT-DEFINED BUILD RULES ###
225+
# This section attempts to build the Python core, the supervisor, and any
226+
# port-provided source code.
227+
#
228+
# QSTR sources are provided for the initial build step, which generates
229+
# Python constants to represent C data which gets passed into the GC.
230+
231+
SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \
232+
$(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \
233+
$(addprefix common-hal/, $(SRC_COMMON_HAL))
234+
235+
SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \
236+
$(addprefix shared-module/, $(SRC_SHARED_MODULE)) \
237+
$(addprefix shared-module/, $(SRC_SHARED_MODULE_INTERNAL))
238+
239+
# There are duplicates between SRC_COMMON_HAL_EXPANDED and SRC_SHARED_MODULE_EXPANDED,
240+
# because a few modules have files both in common-hal/ and shared-module/.
241+
# Doing a $(sort ...) removes duplicates as part of sorting.
242+
SRC_COMMON_HAL_SHARED_MODULE_EXPANDED = $(sort $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED))
243+
244+
# OBJ includes
245+
OBJ += $(PY_O) $(SUPERVISOR_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
246+
OBJ += $(addprefix $(BUILD)/, $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED:.c=.o))
247+
ifeq ($(INTERNAL_LIBM),1)
248+
OBJ += $(addprefix $(BUILD)/, $(SRC_LIBM:.c=.o))
249+
endif
250+
OBJ += $(addprefix $(BUILD)/, $(SRC_CIRCUITPY_COMMON:.c=.o))
251+
OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o))
252+
OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o))
253+
254+
# List of sources for qstr extraction
255+
SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_CIRCUITPY_COMMON) \
256+
$(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED) $(SRC_MOD)
257+
# Sources that only hold QSTRs after pre-processing.
258+
SRC_QSTR_PREPROCESSOR +=
259+
260+
# Default build target
261+
all: $(BUILD)/firmware.elf $(BUILD)/firmware.hex $(BUILD)/firmware.bin
262+
263+
clean-all:
264+
rm -rf build-*
265+
266+
# Optional flash option when running within an installed MSDK to use OpenOCD
267+
# Mainline OpenOCD does not yet have the MAX32's flash algorithm integrated.
268+
# If the MSDK is installed, flash-msdk can be run to utilize the the modified
269+
# openocd with the algorithms
270+
MAXIM_PATH := $(subst \,/,$(MAXIM_PATH))
271+
OPENOCD ?= $(MAXIM_PATH)/Tools/OpenOCD/openocd
272+
OPENOCD_SCRIPTS ?= $(MAXIM_PATH)/Tools/OpenOCD/scripts
273+
flash-msdk:
274+
$(OPENOCD) -s $(OPENOCD_SCRIPTS) \
275+
-f interface/cmsis-dap.cfg -f target/$(MCU_VARIANT_LOWER).cfg \
276+
-c "program $(BUILD)/firmware.elf verify; init; reset; exit"
277+
278+
# flash target using JLink
279+
JLINK_DEVICE = $(MCU_VARIANT_LOWER)
280+
281+
JLINKEXE ?= JLink.exe
282+
JLINKEXE += -if SWD -device ${JLINK_DEVICE} -speed 10000
283+
COMMAND_FILE := tools/flash_max32.jlink
284+
285+
flash-jlink: $(BUILD)/firmware.bin
286+
@$(JLINKEXE) -device $(MCU_VARIANT_UPPER) -NoGui 1 -CommandFile ${COMMAND_FILE}
287+
288+
$(BUILD)/firmware.elf: $(OBJ)
289+
$(STEPECHO) "LINK $@"
290+
$(Q)echo $^ > $(BUILD)/firmware.objs
291+
$(Q)$(CC) -o $@ $(LDFLAGS) @$(BUILD)/firmware.objs -Wl,--print-memory-usage -Wl,--start-group $(LIBS) -Wl,--end-group
292+
$(Q)$(SIZE) $@ | $(PYTHON) $(TOP)/tools/build_memory_info.py $(LINKERFILE) $(BUILD)
293+
294+
$(BUILD)/firmware.hex: $(BUILD)/firmware.elf
295+
$(STEPECHO) "Create $@"
296+
$(Q)$(OBJCOPY) -O ihex $^ $@
297+
298+
$(BUILD)/firmware.bin: $(BUILD)/firmware.elf
299+
$(STEPECHO) "Create $@"
300+
$(Q)$(OBJCOPY) -O binary $^ $@
301+
302+
# *******************************************************************************
303+
### CKTPY BUILD RULES ###
304+
include $(TOP)/py/mkrules.mk

ports/analog/README.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Analog Devices "MAX32" MCUs
2+
3+
This port brings CircuitPython to ADI's "MAX32" series of microcontrollers. These devices are mostly ARM Cortex-M4-based and focus on delivering performance at low-power levels. Currently this port only supports MAX32690.
4+
5+
## Structure of this port
6+
7+
- **`boards/:`** Board-specific definitions including pins, board initialization, etc.
8+
- **`common-hal/:`** Port-specific implementations of CircuitPython common-hal APIs. When a new module is enabled, this is often where the implementation is found. Expected functions for modules in `common-hal` are usually found in `shared-bindings/` or `shared-module/` in the CircuitPy root directory.
9+
- **`linking/:`** Linkerfiles customized for CircuitPython. These are distinct from the linkerfiles used in MSDK as they adopt the structure required by CircuitPython. They may also omit unused features and memory sections, e.g. Mailboxes, RISC-V Flash, & Hyperbus RAM for MAX32690.
10+
- **`msdk:/`** SDK for MAX32 devices. More info on our GitHub: [Analog Devices MSDK GitHub](https://github.com/analogdevicesinc/msdk)
11+
- **`peripherals:/`** Helper files for peripherals such as clocks, gpio, etc. These files tend to be specific to vendor SDKs and provide some useful functions for the common-hal interfaces.
12+
- **`supervisor/:`** Implementation files for the CircuitPython supervisor. This includes port setup, usb, and a filesystem on a storage medium such as SD Card/eMMC, QSPI Flash, or internal flash memory. Currently the internal flash is used. This folder is the most important part of a port's core functionality for CircuitPython.
13+
- **`supervisor/port.c:`** Port-specific startup code including clock initialization, console startup, etc.
14+
15+
- `. :` Build system and high-level interface to the CircuitPython core for the ADI port.
16+
17+
## Building for MAX32 devices
18+
19+
Ensure CircuitPython dependencies are up-to-date by following the CircuitPython introduction on Adafruit's Website: [Building CircuitPython - Introduction](https://learn.adafruit.com/building-circuitpython/introduction). You will require the [ARM GNU Toolchain](https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads), with ARM GCC >=13.x. It is also necessary to fetch all submodules and build the `mpy-cross` compiler, per the "Building CircuitPython" guide.
20+
21+
Ensure the ARM toolchain is contained on your PATH. This can be done in MinGW or WSL by exporting a prefix to the PATH variable. The author's path is included below as an example:
22+
23+
$ export ARM_GNU_PATH=C:/x-tools/arm-win/arm-none-eabi-w64-i686-13.3rel1/bin
24+
$ export PATH=$ARM_GNU_PATH:$PATH
25+
26+
This needs to be done each time you open a command environment to build CircuitPython. It can be useful to set up a simple shell script for this.
27+
28+
Once you have built `mpy-cross` and set up your build system for CircuitPython, you can build for MAX32 devices using the following commands:
29+
30+
$ cd ports/analog
31+
$ make BOARD=<board from boards/ directory>
32+
33+
Be aware the build may take a long time without parallelizing via the `-jN` flag, where N is the # of cores on your machine.
34+
35+
## Flashing the board
36+
37+
Universal instructions on flashing MAX32 devices this project can be found in the **[MSDK User Guide](https://analogdevicesinc.github.io/msdk/USERGUIDE/)**.
38+
39+
In addition, a user may flash the device by calling `make` with the `flash-msdk` target from within the `ports/analog` directory, as below:
40+
41+
```
42+
$ make BOARD=<target board> flash-msdk
43+
```
44+
45+
This requires the following:
46+
- A MAX32625PICO is connected to the PC via USB
47+
- The PICO board shows up as a "DAPLINK" drive which implements the CMSIS-DAP interface.
48+
- The PICO board is connected to the target board via a 10-pin SWD ribbon cable.
49+
- If SWD connectors are not keyed, the P1 indicator (red line) on the SWD ribbon cable should match the P1 indicator on the board silkscreen near the 10-pin SWD connector.
50+
51+
## Using the REPL
52+
53+
Once the device is plugged in, it will enumerate via USB as both a USB Serial Device (CDC) and a Mass Storage Device (MSC). You can connect to the Python REPL with your favorite Serial Monitor program e.g. TeraTerm, VS Code, Putty, etc. Use any buadrate with 8-bit, No Parity, 1 Stop Bit (8N1) settings. From this point forward, you can run Python code on the MCU! If you want help with learning CircuitPython-specific code or learning Python in general, a good place to start is Adafruit's ["Welcome to CircuitPython"](https://learn.adafruit.com/welcome-to-circuitpython/) guide.
54+
55+
## Editing code.py
56+
57+
Python code may be executed from `code.py` the `CIRCUITPY:` drive. When editing this file, please be aware that some text editors will work better than others. A list of suggested text editors can be found at Adafruit's guide here: https://learn.adafruit.com/welcome-to-circuitpython/recommended-editors
58+
59+
Once you save `code.py`, it gets written back to the device you are running Circuitpython on, and will automatically run and output it's result to the REPL. You can also automatically reload and run code.py any time from the REPL by pressing CTRL+D.

0 commit comments

Comments
 (0)