forked from micropython/micropython
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9667 from Brandon-Hurst/port/max32690
Add support for ADI MAX32690 microcontroller
- Loading branch information
Showing
52 changed files
with
3,406 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,304 @@ | ||
# 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 | ||
|
||
# Includes mpconfigboard.mk & mpconfigport.mk, | ||
# along with numerous other shared environment makefiles. | ||
include ../../py/circuitpy_mkenv.mk | ||
|
||
CROSS_COMPILE = arm-none-eabi- | ||
|
||
# MCU_SERIES e.g. "max32" | ||
# MCU_VARIANT e.g. "max32690" | ||
# defined in mpconfigboard.mk | ||
MCU_SERIES_LOWER := $(shell echo $(MCU_SERIES) | tr '[:upper:]' '[:lower:]') | ||
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) | ||
|
||
# For debugging the build | ||
ifneq ($(BUILD_VERBOSE),"") | ||
$(info MSDK_ROOT is $(MSDK_ROOT)) | ||
$(info MSDK_LIBS is $(MSDK_LIBS)) | ||
$(info CMSIS_ROOT is $(CMSIS_ROOT)) | ||
$(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)) | ||
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 | ||
ifeq ($(MCU_VARIANT_LOWER), "max32690") | ||
DIE_TYPE=me18 | ||
else | ||
DIE_TYPE=me18 | ||
endif | ||
|
||
PERIPH_SRC = $(ADI_PERIPH)/Source | ||
|
||
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 | ||
|
||
INC += \ | ||
-I$(TOP)/$(BOARD_PATH) \ | ||
-I$(TOP)/lib/cmsis/inc \ | ||
-I$(CMSIS_ROOT)/Include \ | ||
-I$(CMSIS_ROOT)/Device/Maxim/$(MCU_VARIANT_UPPER)/Include \ | ||
-I$(ADI_PERIPH)/Include/$(MCU_VARIANT_UPPER) \ | ||
-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 | ||
|
||
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 | ||
|
||
SRC_C += $(SRC_MAX32) \ | ||
boards/$(BOARD)/board.c \ | ||
boards/$(BOARD)/pins.c \ | ||
peripherals/$(MCU_VARIANT_LOWER)/pins.c \ | ||
peripherals/$(MCU_VARIANT_LOWER)/gpios.c | ||
|
||
# ******************************************************************************* | ||
### Compiler & Linker Flags ### | ||
COMPILER ?= GCC | ||
|
||
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 | ||
|
||
# CircuitPython custom linkerfile (necessary for build steps & filesystems) | ||
LINKERFILE = linking/$(MCU_VARIANT_LOWER)_cktpy.ld | ||
LDFLAGS += -nostartfiles -specs=nano.specs | ||
endif | ||
|
||
SRC_S += supervisor/cpu.s \ | ||
$(STARTUPFILE) | ||
|
||
# Needed to compile some MAX32 headers | ||
CFLAGS += -D$(MCU_VARIANT_UPPER) \ | ||
-DTARGET_REV=0x4131 \ | ||
-DTARGET=$(MCU_VARIANT_UPPER) \ | ||
-DIAR_PRAGMAS=0 \ | ||
-DRISCV_LOAD=0 \ | ||
-DCONFIG_TRUSTED_EXECUTION_SECURE=0 | ||
|
||
# todo: add these for linkerfiles later on so that it's easier to add new boards | ||
# -DFLASH_ORIGIN \ | ||
# -DFLASH_SIZE \ | ||
# -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) \ | ||
-DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED \ | ||
-DCFG_TUSB_OS=OPT_OS_NONE \ | ||
-DCFG_TUD_CDC_TX_BUFSIZE=1024 \ | ||
-DCFG_TUD_CDC_RX_BUFSIZE=1024 \ | ||
-DCFG_TUD_MSC_BUFSIZE=4096 \ | ||
-DCFG_TUD_MIDI_RX_BUFSIZE=128 \ | ||
-DCFG_TUD_MIDI_TX_BUFSIZE=128 \ | ||
-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 | ||
CFLAGS += -Wno-error=unused-parameter \ | ||
-Wno-error=old-style-declaration \ | ||
-Wno-error=sign-compare \ | ||
-Wno-error=strict-prototypes \ | ||
-Wno-error=cast-qual \ | ||
-Wno-error=unused-variable \ | ||
-Wno-error=lto-type-mismatch \ | ||
-Wno-error=cast-align \ | ||
-Wno-error=nested-externs \ | ||
-Wno-error=sign-compare \ | ||
-Wno-cast-align \ | ||
-Wno-sign-compare \ | ||
|
||
ENTRY = Reset_Handler | ||
LDFLAGS += $(CFLAGS) --entry $(ENTRY) -Wl,-nostdlib -Wl,-T,$(LINKERFILE) -Wl,-Map=$@.map -Wl,-cref -Wl,-gc-sections | ||
LIBS := -lgcc -lc | ||
|
||
# If not using CKTPY mathlib, use toolchain mathlib | ||
ifndef INTERNAL_LIBM | ||
LIBS += -lm | ||
endif | ||
|
||
# ******************************************************************************* | ||
### PORT-DEFINED BUILD RULES ### | ||
# This section attempts to build the Python core, the supervisor, and any | ||
# port-provided source code. | ||
# | ||
# QSTR sources are provided for the initial build step, which generates | ||
# Python constants to represent C data which gets passed into the GC. | ||
|
||
SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ | ||
$(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \ | ||
$(addprefix common-hal/, $(SRC_COMMON_HAL)) | ||
|
||
SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \ | ||
$(addprefix shared-module/, $(SRC_SHARED_MODULE)) \ | ||
$(addprefix shared-module/, $(SRC_SHARED_MODULE_INTERNAL)) | ||
|
||
# There are duplicates between SRC_COMMON_HAL_EXPANDED and SRC_SHARED_MODULE_EXPANDED, | ||
# because a few modules have files both in common-hal/ and shared-module/. | ||
# Doing a $(sort ...) removes duplicates as part of sorting. | ||
SRC_COMMON_HAL_SHARED_MODULE_EXPANDED = $(sort $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED)) | ||
|
||
# OBJ includes | ||
OBJ += $(PY_O) $(SUPERVISOR_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) | ||
OBJ += $(addprefix $(BUILD)/, $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED:.c=.o)) | ||
ifeq ($(INTERNAL_LIBM),1) | ||
OBJ += $(addprefix $(BUILD)/, $(SRC_LIBM:.c=.o)) | ||
endif | ||
OBJ += $(addprefix $(BUILD)/, $(SRC_CIRCUITPY_COMMON:.c=.o)) | ||
OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) | ||
OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) | ||
|
||
# List of sources for qstr extraction | ||
SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_CIRCUITPY_COMMON) \ | ||
$(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED) $(SRC_MOD) | ||
# Sources that only hold QSTRs after pre-processing. | ||
SRC_QSTR_PREPROCESSOR += | ||
|
||
# Default build target | ||
all: $(BUILD)/firmware.elf $(BUILD)/firmware.hex $(BUILD)/firmware.bin | ||
|
||
clean-all: | ||
rm -rf build-* | ||
|
||
# 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 | ||
# openocd with the algorithms | ||
MAXIM_PATH := $(subst \,/,$(MAXIM_PATH)) | ||
OPENOCD ?= $(MAXIM_PATH)/Tools/OpenOCD/openocd | ||
OPENOCD_SCRIPTS ?= $(MAXIM_PATH)/Tools/OpenOCD/scripts | ||
flash-msdk: | ||
$(OPENOCD) -s $(OPENOCD_SCRIPTS) \ | ||
-f interface/cmsis-dap.cfg -f target/$(MCU_VARIANT_LOWER).cfg \ | ||
-c "program $(BUILD)/firmware.elf verify; init; reset; exit" | ||
|
||
# flash target using JLink | ||
JLINK_DEVICE = $(MCU_VARIANT_LOWER) | ||
|
||
JLINKEXE ?= JLink.exe | ||
JLINKEXE += -if SWD -device ${JLINK_DEVICE} -speed 10000 | ||
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 $(LINKERFILE) $(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 ### | ||
include $(TOP)/py/mkrules.mk |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# Analog Devices "MAX32" MCUs | ||
|
||
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. | ||
|
||
## Structure of this port | ||
|
||
- **`boards/:`** Board-specific definitions including pins, board initialization, etc. | ||
- **`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. | ||
- **`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. | ||
- **`msdk:/`** SDK for MAX32 devices. More info on our GitHub: [Analog Devices MSDK GitHub](https://github.com/analogdevicesinc/msdk) | ||
- **`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. | ||
- **`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. | ||
- **`supervisor/port.c:`** Port-specific startup code including clock initialization, console startup, etc. | ||
|
||
- `. :` Build system and high-level interface to the CircuitPython core for the ADI port. | ||
|
||
## Building for MAX32 devices | ||
|
||
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. | ||
|
||
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: | ||
|
||
$ export ARM_GNU_PATH=C:/x-tools/arm-win/arm-none-eabi-w64-i686-13.3rel1/bin | ||
$ export PATH=$ARM_GNU_PATH:$PATH | ||
|
||
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. | ||
|
||
Once you have built `mpy-cross` and set up your build system for CircuitPython, you can build for MAX32 devices using the following commands: | ||
|
||
$ cd ports/analog | ||
$ make BOARD=<board from boards/ directory> | ||
|
||
Be aware the build may take a long time without parallelizing via the `-jN` flag, where N is the # of cores on your machine. | ||
|
||
## Flashing the board | ||
|
||
Universal instructions on flashing MAX32 devices this project can be found in the **[MSDK User Guide](https://analogdevicesinc.github.io/msdk/USERGUIDE/)**. | ||
|
||
In addition, a user may flash the device by calling `make` with the `flash-msdk` target from within the `ports/analog` directory, as below: | ||
|
||
``` | ||
$ make BOARD=<target board> flash-msdk | ||
``` | ||
|
||
This requires the following: | ||
- A MAX32625PICO is connected to the PC via USB | ||
- The PICO board shows up as a "DAPLINK" drive which implements the CMSIS-DAP interface. | ||
- The PICO board is connected to the target board via a 10-pin SWD ribbon cable. | ||
- 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. | ||
|
||
## Using the REPL | ||
|
||
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. | ||
|
||
## Editing code.py | ||
|
||
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 | ||
|
||
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. |
Oops, something went wrong.