diff --git a/MicroPython-New-Port-Development-Guide.md b/MicroPython-New-Port-Development-Guide.md new file mode 100644 index 0000000..81539ad --- /dev/null +++ b/MicroPython-New-Port-Development-Guide.md @@ -0,0 +1,829 @@ +# MicroPython New Port Development Guide + +This comprehensive guide walks through creating a new MicroPython port, using the Alif port development as a case study. The guide is based on analysis of commit `ccc5935234` and subsequent development commits. + +## Overview + +A MicroPython port adapts the core MicroPython runtime to a specific hardware platform. This involves: +- **Hardware Abstraction Layer (HAL)**: Interfacing with hardware-specific drivers +- **Build System**: Integrating with toolchains and hardware SDKs +- **Board Support**: Defining board-specific configurations +- **Peripheral Support**: Implementing machine module interfaces for hardware peripherals + +## Prerequisites + +Before starting, ensure you have: +- Target hardware documentation and SDK/drivers +- Cross-compilation toolchain (typically `arm-none-eabi-` for ARM Cortex-M) +- Understanding of your hardware's memory layout, peripherals, and boot process +- MicroPython source code and build environment + +## Development Phases + +The Alif port development followed this logical progression: +1. **Foundation** - Core infrastructure and basic I/O +2. **System Services** - Timing, interrupts, memory management +3. **Peripheral Support** - Progressive addition of hardware interfaces +4. **Advanced Features** - Multi-core, networking, etc. + +--- + +## Phase 1: Foundation (Essential Files) + +### Step 1: Create Port Directory Structure + +```bash +mkdir ports/YOUR_PORT +cd ports/YOUR_PORT +``` + +Create these essential directories: +- `boards/` - Board-specific configurations +- `mcu/` - MCU-specific files (linker scripts, pin definitions) +- `modules/` - Port-specific Python modules + +### Step 2: Core Configuration Files + +#### A. `mpconfigport.h` (Port Configuration) + +**Purpose**: Defines which MicroPython features are enabled for your port. + +**Common Pattern Analysis**: +- All ports include `mpconfigboard.h` for board-specific overrides +- Use `MICROPY_CONFIG_ROM_LEVEL` for feature sets (MINIMAL/BASIC/EXTRA/FULL) +- Define platform string: `#define MICROPY_PY_SYS_PLATFORM "yourport"` + +**Template from Alif**: +```c +// Options controlling how MicroPython is built, overriding defaults in py/mpconfig.h + +#include +#include + +// board specific definitions +#include "mpconfigboard.h" + +#ifndef MICROPY_CONFIG_ROM_LEVEL +#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_FULL_FEATURES) +#endif + +// Hardware features +#define MICROPY_HW_ENABLE_UART_REPL (1) +#define MICROPY_HW_ENABLE_USBDEV (1) + +// USB configuration +#define MICROPY_HW_USB_CDC (1) +#define MICROPY_HW_USB_VID (0xf055) +#define MICROPY_HW_USB_PID (0x9802) + +// Memory and performance +#define MICROPY_ALLOC_PATH_MAX (128) +#define MICROPY_QSTR_BYTES_IN_HASH (1) + +// MicroPython emitters (for ARM Cortex-M) +#define MICROPY_EMIT_THUMB (1) +#define MICROPY_EMIT_THUMB_ARMV7M (1) +#define MICROPY_EMIT_INLINE_THUMB (1) + +// Core Python features +#define MICROPY_ENABLE_GC (1) +#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) +#define MICROPY_SCHEDULER_DEPTH (8) + +// Platform identification +#define MICROPY_PY_SYS_PLATFORM "yourport" + +// Extended modules +#define MICROPY_PY_MACHINE (1) +#define MICROPY_PY_MACHINE_INCLUDEFILE "ports/yourport/modmachine.c" +#define MICROPY_VFS (1) + +// Type definitions +typedef intptr_t mp_int_t; +typedef uintptr_t mp_uint_t; +typedef intptr_t mp_off_t; + +// Board hooks (define these as no-ops initially) +#ifndef MICROPY_BOARD_STARTUP +#define MICROPY_BOARD_STARTUP() +#endif + +#ifndef MICROPY_BOARD_EARLY_INIT +#define MICROPY_BOARD_EARLY_INIT() +#endif +``` + +#### B. `mpconfigport.mk` (Build Configuration) + +**Purpose**: Makefile variables for the port. + +```makefile +# MicroPython features +MICROPY_VFS_FAT = 1 +MICROPY_VFS_LFS2 = 1 + +# Optimization +COPT = -Os -DNDEBUG + +# Floating point +MICROPY_FLOAT_IMPL = double +``` + +#### C. `qstrdefsport.h` (Port-Specific Strings) + +**Purpose**: Define port-specific interned strings (QSTRs). + +```c +// qstr definitions for this port + +// Example entries: +// Q(Pin) +// Q(UART) +// Q(I2C) +``` + +### Step 3: Hardware Abstraction Layer + +#### A. `mphalport.h` (HAL Interface) + +**Purpose**: Defines the hardware abstraction interface. + +**Common Pattern**: All ports define these core macros: +- `MICROPY_BEGIN_ATOMIC_SECTION()` / `MICROPY_END_ATOMIC_SECTION()` +- Pin manipulation macros +- Timing functions + +**Template from Alif**: +```c +#include "py/ringbuf.h" +#include "shared/runtime/interrupt_char.h" +#include "irq.h" + +// Atomic sections (critical sections) +#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq() +#define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state) + +// Event handling for efficient wait +#define MICROPY_INTERNAL_WFE(TIMEOUT_MS) \ + do { \ + if ((TIMEOUT_MS) < 0) { \ + __WFE(); \ + } else { \ + /* TODO: implement timeout */ \ + } \ + } while (0) + +// Declare pin type and manipulation functions +extern const mp_obj_type_t pin_type; +typedef struct _pin_obj_t { + mp_obj_base_t base; + qstr name; + // ... hardware-specific fields +} pin_obj_t; +``` + +#### B. `mphalport.c` (HAL Implementation) + +**Purpose**: Implements the hardware abstraction functions. + +**Key Functions** (analyze STM32/RP2 implementations): +- `mp_hal_delay_ms()` / `mp_hal_delay_us()` +- `mp_hal_ticks_ms()` / `mp_hal_ticks_us()` +- `mp_hal_stdout_tx_strn()` (debug output) +- `mp_hal_stdin_rx_chr()` (console input) + +### Step 4: Main Entry Point + +#### `main.c` (Application Entry) + +**Purpose**: Main application loop and MicroPython initialization. + +**Common Pattern Analysis** (all ports follow this structure): + +```c +#include "py/runtime.h" +#include "py/gc.h" +#include "py/mperrno.h" +#include "py/mphal.h" +#include "py/stackctrl.h" +#include "shared/runtime/pyexec.h" + +// Hardware-specific includes +#include "your_hardware_headers.h" + +// Memory layout (defined in linker script) +extern uint8_t __StackTop, __StackLimit; +extern uint8_t __GcHeapStart, __GcHeapEnd; + +void _start(void) { + // 1. Hardware initialization + SystemInit(); // Clock setup, etc. + + // 2. Board-specific startup + MICROPY_BOARD_STARTUP(); + + // 3. Initialize interrupt system + SysTick_Config(SystemCoreClock / 1000); + + // 4. Early hardware init + MICROPY_BOARD_EARLY_INIT(); + + // 5. Initialize peripherals + uart_init(); // For REPL + flash_init(); // For filesystem + + // 6. Set up MicroPython memory management + mp_stack_set_top(&__StackTop); + mp_stack_set_limit(&__StackTop - &__StackLimit - 1024); + gc_init(&__GcHeapStart, &__GcHeapEnd); + + // 7. Main execution loop + for (;;) { + // Initialize MicroPython runtime + mp_init(); + + // Initialize subsystems + readline_init0(); + + // Execute boot scripts + pyexec_frozen_module("_boot.py", false); + + // Execute user scripts + int ret = pyexec_file_if_exists("boot.py"); + if (ret & PYEXEC_FORCED_EXIT) { + goto soft_reset_exit; + } + + // Main REPL loop + for (;;) { + if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { + if (pyexec_raw_repl() != 0) break; + } else { + if (pyexec_friendly_repl() != 0) break; + } + } + + soft_reset_exit: + mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n"); + gc_sweep_all(); + mp_deinit(); + } +} + +// Required MicroPython callbacks +void gc_collect(void) { + gc_collect_start(); + gc_helper_collect_regs_and_stack(); + gc_collect_end(); +} + +void nlr_jump_fail(void *val) { + mp_printf(&mp_plat_print, "FATAL: uncaught exception %p\n", val); + mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(val)); + for (;;) { + __WFE(); + } +} +``` + +### Step 5: Build System + +#### A. `Makefile` (Build Configuration) + +**Purpose**: Defines how to build the port. + +**Common Pattern Analysis**: +- Board selection: `BOARD ?= DEFAULT_BOARD` +- Include core makefiles: `include ../../py/mkenv.mk` +- Cross-compiler: `CROSS_COMPILE ?= arm-none-eabi-` +- Git submodules for dependencies + +**Build System Architecture Choices**: + +1. **Pure Make** (STM32, SAMD, Alif) + - Traditional approach for bare-metal ports + - Direct control over build process + - No external build system dependencies + +2. **Make wrapping CMake** (ESP32, RP2) + - Required when vendor SDKs mandate CMake + - Make provides consistent user interface + - CMake handles vendor-specific complexity + + **ESP32 Example**: + ```makefile + # Makefile for MicroPython on ESP32. + # This is a simple, convenience wrapper around idf.py (which uses cmake). + + all: + $(Q)idf.py $(IDFPY_FLAGS) -B $(BUILD) build + ``` + + **RP2 Example**: + ```makefile + # Makefile for micropython on Raspberry Pi RP2 + # This is a simple wrapper around cmake + + all: + $(Q)[ -e $(BUILD)/Makefile ] || cmake -S . -B $(BUILD) -DPICO_BUILD_DOCS=0 ${CMAKE_ARGS} + $(Q)$(MAKE) $(MAKE_ARGS) -C $(BUILD) + ``` + +**Key Insight**: The Make wrapper pattern allows MicroPython to maintain a consistent `make` interface across all ports while accommodating vendor requirements. Users always run `make BOARD=xxx` regardless of underlying build system. + +**Template from Alif (Pure Make)**: +```makefile +################################################################################ +# Initial setup of Makefile environment + +BOARD ?= DEFAULT_BOARD +BOARD_DIR ?= boards/$(BOARD) +BUILD ?= build-$(BOARD) + +ifeq ($(wildcard $(BOARD_DIR)/.),) +$(error Invalid BOARD specified: $(BOARD_DIR)) +endif + +include ../../py/mkenv.mk +include mpconfigport.mk +include $(BOARD_DIR)/mpconfigboard.mk + +# qstr definitions (must come before including py.mk) +QSTR_DEFS += qstrdefsport.h + +# include py core make definitions +include $(TOP)/py/py.mk +include $(TOP)/extmod/extmod.mk + +################################################################################ +# Project specific settings + +CROSS_COMPILE ?= arm-none-eabi- +GIT_SUBMODULES += lib/tinyusb + +# Include paths +INC += -I. +INC += -I$(TOP) +INC += -I$(BUILD) +INC += -I$(BOARD_DIR) + +# Source files +SRC_C = \ + main.c \ + mphalport.c \ + modmachine.c \ + machine_pin.c \ + +# Hardware-specific sources +SRC_C += \ + your_hardware_drivers.c \ + +OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) + +all: $(BUILD)/firmware.elf + +$(BUILD)/firmware.elf: $(OBJ) + $(ECHO) "LINK $@" + $(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS) + +include $(TOP)/py/mkrules.mk +``` + +### Step 6: Board Configuration + +#### A. `boards/YOUR_BOARD/mpconfigboard.h` + +**Purpose**: Board-specific hardware definitions. + +```c +// Board-specific configuration + +#define MICROPY_HW_BOARD_NAME "Your Board Name" +#define MICROPY_HW_MCU_NAME "Your MCU" + +// Pin definitions +#define MICROPY_HW_UART_REPL_TX pin_A9 +#define MICROPY_HW_UART_REPL_RX pin_A10 + +// Flash configuration +#define MICROPY_HW_FLASH_SIZE_MB (2) + +// Enable features for this board +#define MICROPY_HW_ENABLE_USB (1) +#define MICROPY_HW_ENABLE_SDCARD (0) +``` + +#### B. `boards/YOUR_BOARD/mpconfigboard.mk` + +**Purpose**: Board-specific build settings. + +```makefile +MCU_SERIES = your_mcu_series +CMSIS_MCU = YOUR_MCU_DEFINE +STARTUP_FILE = lib/your_sdk/startup_your_mcu.s + +# Linker script +LD_FILES = mcu/your_mcu.ld +``` + +--- + +## Phase 2: System Services + +### Step 7: Interrupt and Timing System + +#### A. `irq.h` (Interrupt Priorities) + +**Purpose**: Define interrupt priority levels. + +```c +// IRQ priority definitions +#define IRQ_PRI_SYSTICK (1) +#define IRQ_PRI_UART (6) +#define IRQ_PRI_USB (6) +#define IRQ_PRI_PENDSV (15) // Lowest priority +``` + +#### B. `pendsv.c` & `pendsv.h` (PendSV Handler) + +**Purpose**: Handle deferred processing (background tasks). + +**Pattern**: Used by networking, Bluetooth, and other async operations. + +### Step 8: Memory Management + +#### A. Linker Script (`mcu/your_mcu.ld`) + +**Purpose**: Define memory layout for the target MCU. + +```ld +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 512K +} + +/* Stack at top of RAM */ +__StackTop = ORIGIN(RAM) + LENGTH(RAM); +__StackLimit = __StackTop - 64K; + +/* Heap for MicroPython GC */ +__GcHeapStart = _end; +__GcHeapEnd = __StackLimit; +``` + +--- + +## Phase 3: Basic Machine Module + +### Step 9: Machine Module Foundation + +#### A. `modmachine.c` (Machine Module) + +**Purpose**: Implements the `machine` module. + +**Common Pattern** (analyze STM32 implementation): + +```c +#include "py/runtime.h" +#include "extmod/modmachine.h" + +// Forward declarations for machine classes +extern const mp_obj_type_t machine_pin_type; + +static mp_obj_t machine_reset(void) { + NVIC_SystemReset(); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset); + +static mp_obj_t machine_unique_id(void) { + // Return unique device ID + return mp_obj_new_bytes((const byte*)&your_unique_id, sizeof(your_unique_id)); +} +static MP_DEFINE_CONST_FUN_OBJ_0(machine_unique_id_obj, machine_unique_id); + +static const mp_rom_map_elem_t machine_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_machine) }, + + { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) }, + { MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) }, + + // Machine classes + { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, +}; +static MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); + +const mp_obj_module_t machine_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&machine_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_machine, machine_module); +``` + +### Step 10: Pin Support + +#### A. `machine_pin.c` (GPIO Implementation) + +**Purpose**: Implement `machine.Pin` class for GPIO control. + +**Common Pattern Analysis** (study STM32/RP2 implementations): + +```c +#include "py/runtime.h" +#include "py/mphal.h" +#include "extmod/modmachine.h" + +typedef struct _machine_pin_obj_t { + mp_obj_base_t base; + qstr name; + uint32_t pin_id; + // Hardware-specific fields + GPIO_TypeDef *gpio; + uint32_t pin_mask; +} machine_pin_obj_t; + +// Pin mapping table +const machine_pin_obj_t machine_pin_obj[] = { + {{&machine_pin_type}, MP_QSTR_A0, 0, GPIOA, GPIO_PIN_0}, + {{&machine_pin_type}, MP_QSTR_A1, 1, GPIOA, GPIO_PIN_1}, + // ... more pins +}; + +static void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "Pin(%q)", self->name); +} + +mp_obj_t machine_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_id, ARG_mode, ARG_pull, ARG_value }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_mode, MP_ARG_INT, {.u_int = GPIO_MODE_INPUT} }, + { MP_QSTR_pull, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // Get pin object + machine_pin_obj_t *pin = pin_find(args[ARG_id].u_obj); + + // Configure pin + if (args[ARG_mode].u_int != GPIO_MODE_INPUT) { + machine_pin_config(pin, args[ARG_mode].u_int, args[ARG_pull].u_obj); + } + + return MP_OBJ_FROM_PTR(pin); +} + +// Pin methods: value(), init(), etc. +static mp_obj_t machine_pin_value(size_t n_args, const mp_obj_t *args) { + machine_pin_obj_t *self = MP_OBJ_TO_PTR(args[0]); + if (n_args == 1) { + // Get value + return MP_OBJ_NEW_SMALL_INT(HAL_GPIO_ReadPin(self->gpio, self->pin_mask)); + } else { + // Set value + HAL_GPIO_WritePin(self->gpio, self->pin_mask, mp_obj_is_true(args[1])); + return mp_const_none; + } +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_value_obj, 1, 2, machine_pin_value); + +static const mp_rom_map_elem_t machine_pin_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_pin_value_obj) }, + // ... more methods +}; +static MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + machine_pin_type, + MP_QSTR_Pin, + MP_TYPE_FLAG_NONE, + make_new, machine_pin_make_new, + print, machine_pin_print, + locals_dict, &machine_pin_locals_dict +); +``` + +--- + +## Phase 4: Storage and Filesystem + +### Step 11: Flash Storage + +**Purpose**: Implement storage backend for filesystem. + +**Common Pattern**: Implement a flash driver that provides: +- Block read/write interface +- Sector erase functionality +- Integration with `extmod/vfs.c` + +Study the Alif `ospi_flash.c` and `alif_flash.c` implementations. + +### Step 12: USB MSC Support + +**Purpose**: Expose filesystem over USB Mass Storage. + +**Dependencies**: TinyUSB integration (see `usbd.c`, `msc_disk.c`) + +--- + +## Phase 5: Peripheral Support + +### Step 13: Adding Peripheral Classes + +For each peripheral (UART, I2C, SPI, ADC, etc.), follow this pattern: + +#### A. Update Build System + +1. **Add source file to Makefile**: +```makefile +SRC_C += machine_i2c.c +``` + +2. **Add hardware driver** (if needed): +```makefile +ALIF_SRC_C += drivers/source/i2c.c +``` + +#### B. Enable in Configuration + +**In `mpconfigport.h`**: +```c +#define MICROPY_PY_MACHINE_I2C (MICROPY_HW_ENABLE_HW_I2C) +#define MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1 (1) +``` + +#### C. Implement Peripheral Class + +**Pattern Analysis** (from Alif I2C implementation): + +1. **Define object structure**: +```c +typedef struct _machine_i2c_obj_t { + mp_obj_base_t base; + uint32_t i2c_id; + I2C_Type *i2c; // Hardware registers + mp_hal_pin_obj_t scl; // Pin objects + mp_hal_pin_obj_t sda; + uint32_t freq; // Configuration + uint32_t timeout; +} machine_i2c_obj_t; +``` + +2. **Create instance table**: +```c +static machine_i2c_obj_t machine_i2c_obj[] = { + #if defined(MICROPY_HW_I2C0_SCL) + [0] = {{&machine_i2c_type}, 0, (I2C_Type *)I2C0_BASE, MICROPY_HW_I2C0_SCL, MICROPY_HW_I2C0_SDA}, + #endif + // ... more instances +}; +``` + +3. **Implement standard methods**: +- `make_new()` - Object construction and hardware initialization +- `print()` - String representation +- Protocol methods (e.g., `transfer()` for I2C) + +4. **Register with machine module**: +```c +{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, +``` + +--- + +## Phase 6: Advanced Features + +### Step 14: Networking Support + +If your hardware supports networking: + +1. **Enable in configuration**: +```c +#define MICROPY_PY_NETWORK (1) +#define MICROPY_PY_SOCKET (1) +``` + +2. **Implement network interface** in `mpnetworkport.c` + +3. **Add LWIP integration** (if using LWIP stack) + +### Step 15: Bluetooth Support + +For Bluetooth-enabled hardware: + +1. **Choose Bluetooth stack** (BTstack, NimBLE) +2. **Implement HCI transport** in `mpbthciport.c` +3. **Enable in configuration**: +```c +#define MICROPY_PY_BLUETOOTH (1) +``` + +### Step 16: Multi-core Support + +For multi-core MCUs (like Alif Ensemble): + +1. **Implement Open-AMP backend** (`mpmetalport.c`, `mpremoteprocport.c`) +2. **Add core-specific configurations** +3. **Handle inter-core communication** + +--- + +## Phase 7: Testing and Validation + +### Step 17: Testing Strategy + +1. **Unit Tests**: Run MicroPython test suite +```bash +cd ports/unix +make test_full +``` + +2. **Hardware-in-Loop**: Test on actual hardware +```bash +cd ports/yourport +make BOARD=YOUR_BOARD +# Flash and test on hardware +``` + +3. **Peripheral Tests**: Create hardware-specific test scripts + +### Step 18: Documentation + +1. **README.md**: Build instructions, supported features +2. **Board documentation**: Pin assignments, jumper settings +3. **API documentation**: Port-specific extensions + +--- + +## Common Pitfalls and Best Practices + +### Build System Choice +- **Start with pure Make** unless vendor SDK requires otherwise +- **Use Make wrappers** when vendor tools (ESP-IDF, Pico SDK) mandate CMake +- **Document build dependencies** clearly in README +- **Maintain consistent user interface** - always support `make BOARD=xxx` + +### Vendor SDK Integration +- **Document all external dependencies** clearly +- **Provide simplified build options** where possible +- **Don't require vendor IDEs** for basic builds +- **Version lock vendor dependencies** to ensure reproducibility + +When vendor SDKs require CMake: +- ESP32: ESP-IDF uses CMake internally via `idf.py` +- RP2: Pico SDK is CMake-based +- Solution: Wrap vendor tools with Make for consistency + +### Memory Management +- **Always define proper memory regions** in linker script +- **Test with different heap sizes** - GC pressure reveals bugs +- **Use `MP_REGISTER_ROOT_POINTER`** for global objects + +### Interrupt Handling +- **Keep ISRs minimal** - defer work to PendSV/main loop +- **Use proper priorities** - timing-critical > user code > background tasks +- **Test interrupt nesting** scenarios + +### Hardware Integration +- **Follow existing peripheral patterns** - don't reinvent APIs +- **Handle hardware quirks gracefully** (see Alif I2C zero-length transfer workaround) +- **Add proper error handling** and timeouts + +### Build System +- **Use consistent naming** for boards and configurations +- **Minimize external dependencies** - prefer git submodules +- **Support both debug and release builds** + +### Pin Configuration +- **Create comprehensive pin mapping** in `pins.csv` +- **Support alternate functions** for peripherals +- **Handle pin conflicts** (multiple peripherals on same pins) + +--- + +## Maintenance and Evolution + +### Keeping Up with MicroPython +- **Monitor MicroPython releases** for API changes +- **Participate in community** discussions +- **Contribute improvements** back to mainline + +### Adding New Features +- **Follow established patterns** from other ports +- **Add comprehensive tests** for new functionality +- **Document changes** thoroughly + +### Performance Optimization +- **Profile with real workloads** +- **Optimize critical paths** (GC, interrupt handling) +- **Consider hardware-specific optimizations** (DMA, etc.) + +--- + +This guide provides a comprehensive roadmap for developing a new MicroPython port. The key is to start with a minimal working foundation and incrementally add features, following the patterns established by existing successful ports. \ No newline at end of file