Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for ADI MAX32690 microcontroller #9667

Merged
merged 39 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
0374e99
Initial commit for ADI MAX32690 support. Still many modules to implem…
Aug 14, 2024
e8528fa
- Added 1/1024 s tick based on 4096 Hz RTC.
Brandon-Hurst Aug 16, 2024
8978e3e
- (build): Added tinyUSB src/inc, DMA & RTC from MSDK.
Brandon-Hurst Aug 20, 2024
b1ca548
- Fixed stack & heap variables from linkerscript causing HardFaults. …
Brandon-Hurst Aug 20, 2024
79f496f
-Added USB via tinyUSB. Still need to test/debug before REPL is ready…
Aug 23, 2024
04720ec
Fixed USB endpoint speed issue w/ configuration setting
Aug 26, 2024
5374625
Fixed some RTC alarm setup issues; tick interrupts now function as ex…
Brandon-Hurst Sep 2, 2024
1c1d199
Reorganized some build files & commented out WFI to debug USB. USB en…
Brandon-Hurst Sep 3, 2024
e6c4c78
- Fixed USB endpoint descriptor problems. All USB classes should now …
Brandon-Hurst Sep 3, 2024
0fa04e9
- Fixed USB issues. REPL & CIRCUITPY: drive now function correctly! -…
Brandon-Hurst Sep 5, 2024
3f2e39e
Added digitalio module.
Brandon-Hurst Sep 22, 2024
00d95cb
Added max32690 EVKIT board & changed APARD board to apard32690
Brandon-Hurst Sep 23, 2024
58277a4
Reordered mpconfigport.mk; replaced MXC_SYS includes with max32_port.…
Brandon-Hurst Sep 23, 2024
4a8643e
Moved GPIO ports to board.c to make it easy to add boards in the futu…
Brandon-Hurst Sep 27, 2024
ff87a70
Updated USB PID for max32690evkit
Brandon-Hurst Sep 27, 2024
8ee4bfb
Formatting fixes missed by local pre-commit runner
Brandon-Hurst Sep 27, 2024
a8ba80f
Add "analog" to shared_bindings_matrix.py
Brandon-Hurst Sep 27, 2024
df86e3e
More pre-commit fixes.
Brandon-Hurst Sep 27, 2024
1a41f17
Manual pre-commit fix for all requisite files.
Sep 27, 2024
76cc006
Manual pre-commit fix for last delinquent file
Brandon-Hurst Sep 27, 2024
8e753d3
- Move SysTick init from board_init to port_init. - Fix RTC issue wit…
Brandon-Hurst Oct 1, 2024
79d2fc5
- Changed board.c to match silkscreen. - Added digitalio handling for…
Brandon-Hurst Oct 2, 2024
0fe33e1
pre-commit formatting fixes
Oct 2, 2024
8a26949
more pre-commit fixes
Brandon-Hurst Oct 2, 2024
4794886
final pre-commit fix
Brandon-Hurst Oct 2, 2024
efae9e2
Fix CI run issues with docs & tlsf submodule
Brandon-Hurst Oct 2, 2024
dc2c214
- Add elf target for CI build. - Add ports/analog/README to toctree f…
Brandon-Hurst Oct 2, 2024
4a7fe71
Update msdk submodule to clear nvic/dma warnings
Brandon-Hurst Oct 24, 2024
ac19bba
Remove dma_revb.c from Makefile
Brandon-Hurst Oct 24, 2024
7fe51d3
Add CONFIG_TRUSTED_EXECUTION_SECURE macro to Makefile
Brandon-Hurst Oct 24, 2024
b1424e1
Add open-drain to digitalio + Resolve some issues with GPIO4 & settin…
Brandon-Hurst Oct 25, 2024
bd96ff7
Pre-commit formatting fix
Brandon-Hurst Oct 25, 2024
dace5bc
Pre-commit formatting fix
Brandon-Hurst Oct 25, 2024
ecba079
Fix optimization settings for non-debug builds
Nov 3, 2024
4c249d5
Enabled SysTick interrupt for time.sleep to work. Cleaned up optimiza…
Brandon-Hurst Nov 3, 2024
c3a3ae1
Remove FIXME comments from supervisor/port.c. Changes were tested.
Brandon-Hurst Nov 3, 2024
491b7bd
Fix rebase issues and add ARM GCC environment setup to README.md
Brandon-Hurst Nov 25, 2024
2a2ebb9
Remove board_millis() and extra LED bringup code
Brandon-Hurst Nov 27, 2024
24b53f5
Move configuration from board.c to supervisor/port.c (non-MCU specifi…
Brandon-Hurst Nov 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -407,3 +407,6 @@
[submodule "frozen/Adafruit_CircuitPython_Wiznet5k"]
path = frozen/Adafruit_CircuitPython_Wiznet5k
url = https://github.com/adafruit/Adafruit_CircuitPython_Wiznet5k
[submodule "ports/analog/msdk"]
path = ports/analog/msdk
url = https://github.com/analogdevicesinc/msdk.git
1 change: 1 addition & 0 deletions docs/shared_bindings_matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from concurrent.futures import ThreadPoolExecutor

SUPPORTED_PORTS = [
"analog",
"atmel-samd",
"broadcom",
"cxd56",
Expand Down
1 change: 1 addition & 0 deletions docs/supported_ports.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Additional testing is limited.
.. toctree::
:maxdepth: 2

../ports/analog/README
../ports/atmel-samd/README
../ports/broadcom/README
../ports/cxd56/README
Expand Down
303 changes: 303 additions & 0 deletions ports/analog/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,303 @@
# 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

# *******************************************************************************
### 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
59 changes: 59 additions & 0 deletions ports/analog/README.md
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.
Loading