Marlin Agent Skills & AI Rules

GitHub

Marlin is a firmware for RepRap 3D printers optimized for both 8 and 32 bit microcontrollers. Marlin supports all common platforms.

17,520 stars C++ C++ 1 file Β· ~3,651 tokens #3d-printing#arduino#atmel#avr#esp32#firmware#hacktoberfest#reprap
RAW Rules
4 Discovered Rules β€’ ~9,585 Estimated Tokens
Quick:
Loading skill content...

AI Agent Protocol & Instructions

AGENTS.md root-instruction ~8,685 tokens
Raw
# Marlin 3D Printer Firmware

> This file consolidates the project summary (`docs/project-summary.md`) into the top-level agent reference. It is the canonical orientation document for the whole repo. Per-HAL working notes live in `Marlin/src/HAL/<FAMILY>/AGENTS.md` (e.g. `Marlin/src/HAL/AT32/AGENTS.md`).

## 1. Executive Summary

Marlin is an open-source firmware for 3D printers, written in C/C++ and built on the Arduino framework via PlatformIO. It sits between a host computer (running slicer software) and the printer's hardware, translating G-code movement commands into precise stepper motor control, temperature regulation, and peripheral management. The firmware supports 15+ microcontroller platforms (STM32, AVR, ESP32, RP2040, and more), 400+ pin configuration files across 24 board families, and a modular feature system with 80+ enable/disable features. At over 2,500 source files, Marlin is one of the most widely deployed 3D printer firmware projects in the world, licensed under GPL v3.0.

## 2. Architecture Overview

Marlin follows a layered embedded firmware architecture organized around a Hardware Abstraction Layer (HAL), a G-code command processing pipeline, a set of core motion/thermal modules, and a rich feature system. The firmware's singleton entry point is the `Marlin` class (`MarlinCore`), which manages global state and the main control loop.

```mermaid
graph TB
    subgraph Environment["Printer Environment"]
        Host["Host Computer\n(Slicer / Host Software)"]
        SD["SD Card\n(SdFat)"]
        Sensors["Thermistors &\nEndstops"]
        Motors["Stepper Motors\n&amp; Drivers"]
        Heaters["Heaters &amp; Fans"]
        Display["LCD / TFT / DWIN"]
    end

    subgraph Marlin["Marlin Firmware"]
        subgraph GCode["G-Code Subsystem"]
            Queue["GCodeQueue\nRing Buffer"]
            Parser["GCodeParser\nParameter Extraction"]
            Suite["GcodeSuite\nCommand Dispatcher"]
        end
        subgraph Modules["Core Modules"]
            Motion["Motion Planner"]
            Planner["Block Planner"]
            Stepper["Stepper Driver"]
            Temp["Temperature Manager"]
        end
        subgraph Features["Feature System\n80+ modules"]
            BedLevel["Bed Leveling"]
            PowerLoss["Power Loss Recovery"]
            Runout["Filament Runout"]
            MMU["Multi-Material\nUnit"]
        end
        subgraph HAL["Hardware Abstraction Layer"]
            Shared["HAL Shared Code"]
            Platforms["15+ Platform HALs"]
        end
    end

    Host -->|"USB Serial\n250k baud"| Suite
    SD -->|"SD Interface"| Queue
    Suite --> Parser
    Parser --> Suite
    Queue --> Suite
    Suite --> Motion
    Suite --> Temp
    Motion --> Planner
    Planner --> Stepper
    Stepper --> Motors
    Temp --> Heaters
    Temp --> Sensors
    Display <-->|"SPI/I2C/UART"| Suite
```

The firmware communicates with the host via serial at 250,000 baud (configurable), receiving G-code commands line-by-line. Commands are queued in a circular buffer (`GCodeQueue::ring_buffer`), parsed by `GCodeParser`, and dispatched by `GcodeSuite` to category-specific handlers (motion, temperature, configuration, calibration, etc.). The core modules handle the low-level real-time tasks: the planner generates motion blocks with jerk control and acceleration profiling, the stepper driver issues pulse trains, and the temperature manager runs PID loops on thermistor inputs.

### Supported Hardware Platforms

| Platform Family | MCUs | Architecture | Notes |
| --- | --- | --- | --- |
| STM32 (various) | STM32F0, F1, F4, F7, H7, G0 | ARM Cortex-M | Primary 32-bit target |
| AVR | ATmega2560, ATmega1280, AT90USB | 8-bit AVR | Legacy support |
| ESP32 | ESP32-S3, ESP32-S2 | Xtensa/RISC-V | WiFi/BLE capability |
| SAMD | SAMD21, SAMD51 | ARM Cortex-M0+/M4 | Adafruit Feather M4 |
| RP2040 | RP2040, RP2350 | ARM Cortex-M33 | Raspberry Pi Pico |
| LPC | LPC1768, LPC1769 | ARM Cortex-M3 | RAMBo, Melzi boards |
| GD32 | GD32F1, GD32F3 | ARM Cortex-M3 | GigaDevice clones |
| HC32 | HC32F4 | ARM Cortex-M4 | JCEC chips |
| AT32 | AT32F4 | ARM Cortex-M4 | Artery Tek |
| Teensy | 3.1/3.2, 3.5/3.6, 4.0/4.1 | ARM Cortex-M4/M7 | PJRC boards |
| Linux Simulator | x86/x64 | Native | CI/testing |
| Native Simulator | Any | Native | Unit testing |

## 3. Processing Pipeline

The G-code processing pipeline follows a well-defined flow from input ingestion through parsing, dispatch, and hardware actuation.

```mermaid
flowchart TD
    InputSerial["Serial Input\nUSB / UART"] --> Queue
    InputSD["SD Card\nSdFat"] --> Queue
    InputProgmem["Program Memory\nPROGMEM"] --> Queue

    Queue["GCodeQueue\nRing Buffer\nBUFSIZE entries"] --> Parser

    Parser["GCodeParser\nβ€’ Letter/Code/Subcode\nβ€’ Parameter extraction\nβ€’ FASTER_GCODE_PARSER\n  pre-scanned flags"] --> Suite

    Suite["GcodeSuite\nCommand Dispatcher\nβ€’ Subcommand routing\nβ€’ Parameter validation\nβ€’ Endstop events"]

    Suite --> CatMotion["Motion\nG0/G1/G2/G3"]
    Suite --> CatTemp["Temperature\nM104/M105/M106/M107/M109"]
    Suite --> CatConfig["Configuration\nM200-M205/M301/M92"]
    Suite --> CatCalibrate["Calibration\nG28/G33/G34/G425"]
    Suite --> CatSD["SD Card\nM20-M34/M928"]

    CatMotion --> Planner
    CatTemp --> Temp
    CatCalibrate --> Motion

    Planner["Block Planner\nβ€’ Trapezoidal profile\nβ€’ Jerk control\nβ€’ Buffer: BLOCK_BUFFER_SIZE"] --> Stepper
    Motion["Motion\nβ€’ axis_position()\nβ€’ relative_mode\nβ€’ dual_x_carriage"] --> Planner
    Temp["Temperature\nβ€’ PID loops\nβ€’ thermistor tables\nβ€’ safety checks"] --> Heaters

    Stepper["Stepper Driver\nβ€’ issue_pending()\nβ€’ TMC SPI config\nβ€’ Trinamic drivers"] --> Output["Hardware Outputs\nβ€’ Step/Dir pulses\nβ€’ PWM heat/fan\nβ€’ Serial responses"]
```

### Key Pipeline Components

**GCodeQueue** β€” A circular ring buffer (`RingBuffer`) that holds up to `BUFSIZE` G-code command strings. Commands enter via three injectors: serial input (USB/UART), SD card file reading, and in-firmware injected commands (PROGMEM). The queue's `advance()` method pops the next command and hands it to the parser.

**GCodeParser** β€” Parses a single G-code line, extracting the command letter (G/M/T), code number, subcode, and all parameter values (X, Y, Z, E, F, S, P, etc.). When `FASTER_GCODE_PARSER` is enabled, the parser pre-scans all parameters into a flags array for O(1) lookups.

**GcodeSuite** β€” The command dispatcher singleton. Each G/M code maps to a handler method within this class. Commands are routed to category subdirectories under `src/gcode/` (e.g., `motion/`, `temp/`, `config/`, `calibrate/`). The suite also handles pre- and post-command hooks for endstop events, buffer monitoring, and inactivity shutdown.

## 4. Core Components

### 4.1 Firmware Entry Point

The firmware lifecycle is managed by `MarlinCore.cpp` (~1,777 lines), structured around Arduino's `setup()` and `loop()` functions:

- **`setup()`** β€” Initializes HAL pins, serial ports, all modules (stepper, temperature, motion, planner, settings), features (runout detection, power loss recovery, LEDs), and the UI subsystem. Each initialization block is wrapped in `SETUP_RUN()` for debug logging in dev mode.
- **`loop()`** β€” Runs continuously (infinite loop on AVR, structured loop on 32-bit platforms). Each iteration calls `marlin.idle()`, processes the G-code queue, checks power-off timers, and handles endstop events.

### 4.2 Singleton Architecture

Global state is managed through singletons:

| Singleton | File | Responsibility |
| --- | --- | --- |
| `marlin` | `MarlinCore.cpp/h` | Global state machine, inactivity management, kill/suicide, heatup waits |
| `gcode` | `gcode/gcode.cpp` | G-code command dispatch |
| `queue` | `gcode/queue.h` | Command queue ring buffer |
| `planner` | `module/planner.cpp` | Motion block buffer and trapezoidal profiling |
| `stepper` | `module/stepper.cpp` | Step pulse generation and TMC driver config |
| `thermalManager` | `module/temperature.cpp` | PID loops, thermistor reading, safety monitoring |
| `card` | `sd/cardreader.cpp` | SD card file system operations |
| `ui` | `lcd/marlinui.cpp/h` | LCD/UI state machine and menu system |

### 4.3 Module System

The `module/` directory contains the core motion and thermal management classes:

| Module | File | Description |
| --- | --- | --- |
| **Motion** | `motion.h/cpp` | High-level axis positioning, coordinate transforms, joint interpolation |
| **Planner** | `planner.h/cpp` | Block buffer, trapezoidal velocity profiling, junction deviation |
| **Stepper** | `stepper.h/cpp` | Step pulse generation, direction control, TMC Trinamic SPI configuration |
| **Temperature** | `temperature.h/cpp` | PID autotune (M303), thermistor tables, hotend/bed/heater management |
| **Endstops** | `endstops.h/cpp` | Endstop interrupt handling, homing logic, soft endstops |
| **Probe** | `probe.h/cpp` | Bed probing (G30, G31/G32, G38, bltouch), Z-offset management |
| **Settings** | `settings.h/cpp` | EEPROM persistence, configuration storage and retrieval |
| **PrintCounter** | `printcounter.h/cpp` | Print time, filament usage, and job statistics |
| **Servo** | `servo.h/cpp` | Servo control for solenoids, lid mechanisms |
| **Delta/Scara/Polar** | `delta.h`, `scara.h`, `polar.h` | Kinematic transforms for non-Cartesian printers |
| **Tool Change** | `tool_change.h/cpp` | Multi-extruder tool switching, hotend offset, PTFE purge |

### 4.4 Feature System

The `feature/` directory contains 80+ optional modules, each gated by a `#if ENABLED(FEATURE_NAME)` preprocessor check:

**Motion Features:** Linear Advance (`linearadvance`), Pressure Advance, Adaptive Multi-Axis Stepping, Direct Stepping, Bresenham acceleration, Resonance Compensation, X-Axis Twist Correction, Z-Stepper Alignment, Backlash Compensation.

**Thermal Features:** Automatic PID Tuning (M303), Thermal Protection, Probe Temperature Compensation, Mixed Extruder (`mixing`), Bowden/Direct Drive Retraction (`fwretract`).

**Peripheral Features:** Power Loss Recovery (`powerloss`), Filament Runout Detection (`runout`), Ethernet Connectivity (`ethernet`), RS485 Communication (`rs485`), MMU/Multi- Material Unit (`mmu`, `mmu3`), Solenoid Control (`solenoid`), Spindle/Laser (`spindle_laser`), Case Lights (`caselight`), LED Color Control (`leds`).

**UI Features:** Touch Screen (`touch`), LVGL TFT UI (`mks_ui`), DWIN Display (`dwin`), Extensible UI (`extui`), Password Protection (`password`), Joystick Input (`joystick`).

**Bed Leveling:** Unified Bed Leveling (UBL), Manual Bed Leveling (MBL), Automatic Bed Leveling (ABL), G26 Mesh Validation, G35 Auto Bed Leveling, Bed Level Visualizer.

## 5. G-Code Command Reference

Marlin implements 100+ G-code commands organized into 14 categories under `src/gcode/`:

| Category | Directory | Key Commands | Description |
| --- | --- | --- | --- |
| **Motion** | `motion/` | G0, G1, G2, G3, G5, G6, G80, M400, M290 | Linear/arc moves, rapid moves, dwell, wait, jog |
| **Temperature** | `temp/` | M104/M105/M106/M107/M109, M140/M190, M303 | Hotend/bed temp set/read, fan control, PID autotune |
| **Configuration** | `config/` | M200-M205, M301, M92, M43, M218, M217 | Extruder steps, accel/jerk, PID, hotend offset, bowden length |
| **Calibration** | `calibrate/` | G28, G33, G34, G425, M48, M566, M665 | Home, delta calibration, nozzle purge, backlash, bellows |
| **Geometry** | `geometry/` | G17-G19, G53-G59, G92, M206, M428 | Plane selection, coordinate systems, position reset, offsets |
| **Control** | `control/` | M17/M18/M84, M80/M81, M3-M5, M7-M9, T | Enable axes, power, spindle, tool select, feedrate/extruder units |
| **Probe** | `probe/` | G30, G31/G32, G38, M851, M401/M402, M102 | Bed probe, probe type, probe actions |
| **SD Card** | `sd/` | M20-M34, M928, M1001, M1003 | File listing, select, start, stop, abort, load, save |
| **LCD** | `lcd/` | M0, M1, M73, M117, M145, M250, M300 | Pause, progress, message, color, beep |
| **Host** | `host/` | M16, M110, M113, M114, M115, M118, M119, M154, M360, M876 | Line numbers, machine info, endstop report, kinematic config |
| **EEPROM** | `eeprom/` | M500, M501, M502, M503, M504 | Save/load/reset/settings EEPROM operations |
| **Stats** | `stats/` | M31, M75-M78 | Print time, filament used, errors, buffer stats |
| **Units** | `units/` | G20/G21, M82/M83, M149 | mm/inch, extrusion mode, temp unit display |
| **OTA** | `ota/` | M936 | Over-the-air firmware update |

## 6. Infrastructure & Deployment

### 6.1 Build System

Marlin uses PlatformIO as its primary build system, configured via `platformio.ini`:

- **Framework**: Arduino (via PlatformIO)
- **Build flags**: `-g3 -D__MARLIN_FIRMWARE__ -DNDEBUG -fsingle-precision-constant`
- **Source filter**: Dynamic inclusion/exclusion of files based on target board via pre-build scripts (`configuration.py`, `common-dependencies.py`, `preflight-checks.py`)
- **Include directory**: `Marlin/src/`
- **Board definitions**: Custom PlatformIO board definitions in `buildroot/share/PlatformIO/boards/`

### 6.2 Configuration System

Configuration is managed through a layered preprocessor conditional system:

1. **`Configuration.h`** β€” User-editable hardware and feature configuration
2. **`Configuration_adv.h`** β€” Advanced/experimental feature toggles
3. **`Version.h`** β€” Build version, machine name, website URL
4. **`inc/Conditionals-*.h`** β€” Auto-generated feature flags derived from Configuration.h
5. **`inc/MarlinConfig.h`** β€” Prefix header including all conditionals, types, and sanity checks

The conditional system ensures that only enabled features compile, minimizing firmware footprint for resource-constrained 8-bit platforms.

### 6.3 CI/CD Pipeline

GitHub Actions workflows run on every pull request and push:

| Workflow | Purpose |
| --- | --- |
| `ci-build-tests.yml` | Compiles Marlin for all supported boards (matrix strategy) |
| `ci-unit-tests.yml` | Runs C++ unit tests on the native simulator |
| `ci-validate-boards.yml` | Validates board pin configurations |
| `ci-validate-pins.yml` | Checks for missing/invalid pin definitions |
| `ci-validate-lines.yml` | Validates line count limits for 8-bit boards |
| `check-pr.yml` | PR quality checks |

### 6.4 Docker Build Environment

A Dockerfile (`docker/Dockerfile`) provides a reproducible build environment:

```dockerfile
FROM python:3.11-bookworm
RUN pip install -U platformio PyYaml
WORKDIR /code
```

### 6.5 Testing

- **Unit tests**: Located in `Marlin/tests/`, run via the Linux native simulator HAL
- **Build tests**: CI compiles against 20+ board targets to catch compile errors
- **Pin validation**: Automated checks for pin conflicts and missing definitions
- **SdFat**: Integrated SdFat library for SD card file operations (Sd2Card, SdBaseFile, SdVolume)

## 7. Extension Patterns

### 7.1 Adding a New Feature

1. Create your feature files in `Marlin/src/feature/` (e.g., `my_feature.h` and `my_feature.cpp`)
2. Add `#define MY_FEATURE` to `Configuration_adv.h`
3. The conditional system in `inc/Conditionals-*.h` will auto-generate `HAS_MY_FEATURE`
4. Use `#if ENABLED(MY_FEATURE)` guards in your code
5. Include your header from `MarlinCore.cpp` under the appropriate `#if ENABLED()` block
6. Register G-code handlers in `gcode/gcode.cpp` or a new category subdirectory

### 7.2 Adding a New G-Code Command

1. Create a new file in the appropriate `src/gcode/<category>/` directory (e.g., `M1000.cpp`)
2. Implement the handler method in the `GcodeSuite` class
3. Register the command in the `process_commands()` method of `GcodeSuite`
4. The command will be dispatched automatically when the parser encounters the letter/code

### 7.3 Adding Board Support

1. Create a new PlatformIO board definition in `buildroot/share/PlatformIO/boards/`
2. Add pin definitions in `Marlin/src/pins/<family>/pins_<board>.h`
3. If the MCU is new, add HAL support in `Marlin/src/HAL/<MCU_FAMILY>/`
4. Update `ini/<platform>.ini` in `platformio.ini`'s `extra_configs`
5. Run `ci-validate-pins.yml` to verify pin assignments

### 7.4 Adding a Display Backend

1. Create backend files in `Marlin/src/lcd/<backend>/`
2. Implement the required display interface (SPI/I2C/UART)
3. Add `#define ULTIPANEL` or display-specific `#define` to `Configuration.h`
4. The LCD subsystem routes through `MarlinUI` to the appropriate backend

## 8. Rules & Anti-Patterns

### Best Practices

- **Conditional compilation**: Always gate platform-specific code with `#if ENABLED()` or `#ifdef ARDUINO_ARCH_XXX`
- **PROGMEM usage**: Store large strings and lookup tables in program memory on 8-bit platforms
- **Interrupt safety**: Use `WAIT`/`NOOP` patterns for stepper ISR synchronization
- **EEPROM limits**: Respect memory constraints β€” 8-bit boards have limited EEPROM (4KB-8KB)
- **Thread safety**: The main loop and stepper ISR share state β€” use volatile and careful locking
- **Static analysis**: Use `bug_on()` macros for compile-time assertion checks
- **Code size**: 8-bit targets (AVR) have strict flash limits β€” enable only necessary features

### Anti-Patterns

- **Don't add features to `Configuration.h`** β€” use `Configuration_adv.h` for advanced/experimental features
- **Don't modify HAL shared code** without understanding platform implications
- **Don't use floating-point on AVR** without explicit `float` typing β€” the compiler defaults to single precision
- **Don't block in the main loop** β€” all long operations must yield to `idle()` or use non-blocking patterns
- **Don't assume 32-bit semantics** β€” code must compile for both 8-bit AVR and 32-bit ARM
- **Don't hardcode pin numbers** β€” always use the pin definition headers

## 9. Dependencies

### Build Tools

| Dependency       | Version           | Purpose                    |
| ---------------- | ----------------- | -------------------------- |
| PlatformIO       | Latest dev        | Build system and framework |
| Arduino Core     | Platform-specific | Microcontroller SDK        |
| GCC ARM Embedded | 12.x              | ARM cross-compiler         |
| avr-gcc          | 7.x               | AVR cross-compiler         |

### Libraries (integrated)

| Library    | Purpose                                             |
| ---------- | --------------------------------------------------- |
| SdFat      | SD card file system (Sd2Card, SdBaseFile, SdVolume) |
| u8glib     | OLED/LCD display driver (embedded in HAL)           |
| LVGL       | TFT graphical UI (optional, for MKS UI)             |
| heatshrink | G-code decompression for SD prints                  |

### Platform Libraries

| Platform | Libraries                     |
| -------- | ----------------------------- |
| STM32    | STM32 HAL/LL, STM32duino core |
| AVR      | Arduino AVR core, TimerOne    |
| ESP32    | ESP-IDF components, WiFi      |
| RP2040   | Arduino RP2040 core, PIOasm   |
| Teensy   | Teensyduino core, Bounce2     |
| SAMD     | Arduino SAMD core             |

## 10. Code Structure

```
MarlinFirmware/                  # Repo root (this directory). `cd` here for PlatformIO builds.
β”œβ”€β”€ Marlin/                      # The Arduino "sketch" (application source + config files)
β”‚   β”œβ”€β”€ Configuration.h          # User hardware configuration
β”‚   β”œβ”€β”€ Configuration_adv.h      # Advanced/experimental toggles
β”‚   β”œβ”€β”€ Marlin.ino               # Board-specific entry stub
β”‚   β”œβ”€β”€ Makefile                 # Alternative build (simulator)
β”‚   β”œβ”€β”€ Version.h                # Build version, machine name
β”‚   β”œβ”€β”€ config.ini               # PlatformIO extra config
β”‚   β”œβ”€β”€ lib/                     # Integrated libraries
β”‚   └── src/                     # Application source (see below)
β”œβ”€β”€ buildroot/                   # Build infrastructure
β”œβ”€β”€ ini/                         # PlatformIO platform configs
β”œβ”€β”€ docs/                        # Project documentation
β”œβ”€β”€ docker/                      # Docker build environment
β”œβ”€β”€ .github/workflows/           # CI/CD pipelines
└── platformio.ini               # Main PlatformIO configuration
```

### Marlin/src layout

```
Marlin/src/
β”œβ”€β”€ MarlinCore.cpp/h         # Firmware entry, setup(), loop(), Marlin singleton
β”œβ”€β”€ core/                    # Core utilities (serial, language, types, mstring)
β”‚   β”œβ”€β”€ gcode/                   # G-code subsystem
β”‚   β”‚   β”œβ”€β”€ gcode.cpp/h          # GcodeSuite dispatcher
β”‚   β”‚   β”œβ”€β”€ parser.cpp/h         # GCodeParser
β”‚   β”‚   β”œβ”€β”€ queue.cpp/h          # GCodeQueue ring buffer
β”‚   β”‚   β”œβ”€β”€ motion/              # G0-G6, M290, M400
β”‚   β”‚   β”œβ”€β”€ temp/                # M104-M109, M140-M193, M303
β”‚   β”‚   β”œβ”€β”€ config/              # M200-M205, M301, M92, M218
β”‚   β”‚   β”œβ”€β”€ calibrate/           # G28, G33, G34, G425, M48
β”‚   β”‚   β”œβ”€β”€ bedlevel/            # G26, G35, G42, M420
β”‚   β”‚   β”œβ”€β”€ geometry/            # G17-G19, G53-G59, G92
β”‚   β”‚   β”œβ”€β”€ probe/               # G30-G38, M851, M401
β”‚   β”‚   β”œβ”€β”€ sd/                  # M20-M34, M928
β”‚   β”‚   β”œβ”€β”€ lcd/                 # M0, M1, M73, M117
β”‚   β”‚   β”œβ”€β”€ host/                # M16, M110-M119
β”‚   β”‚   β”œβ”€β”€ eeprom/              # M500-M504
β”‚   β”‚   β”œβ”€β”€ stats/               # M31, M75-M78
β”‚   β”‚   β”œβ”€β”€ units/               # G20/G21, M82/M83
β”‚   β”‚   └── control/             # M3-M5, M7-M9, M17-M85, T
β”‚   β”œβ”€β”€ module/                  # Core modules
β”‚   β”‚   β”œβ”€β”€ motion.h/cpp         # Axis positioning, kinematics
β”‚   β”‚   β”œβ”€β”€ planner.h/cpp        # Block buffer, trapezoidal profiling
β”‚   β”‚   β”œβ”€β”€ stepper.h/cpp        # Step pulses, TMC drivers
β”‚   β”‚   β”œβ”€β”€ temperature.h/cpp    # PID, thermistors, safety
β”‚   β”‚   β”œβ”€β”€ endstops.h/cpp       # Endstop interrupts, homing
β”‚   β”‚   β”œβ”€β”€ probe.h/cpp          # Bed probing, Z-offset
β”‚   β”‚   β”œβ”€β”€ settings.h/cpp       # EEPROM persistence
β”‚   β”‚   β”œβ”€β”€ delta.h/cpp          # Delta kinematics
β”‚   β”‚   β”œβ”€β”€ scara.h/cpp          # Scara kinematics
β”‚   β”‚   β”œβ”€β”€ polar.h/cpp          # Polar kinematics
β”‚   β”‚   β”œβ”€β”€ polargraph.h/cpp     # Polar graph kinematics
β”‚   β”‚   β”œβ”€β”€ servo.h/cpp          # Servo control
β”‚   β”‚   β”œβ”€β”€ printcounter.h/cpp   # Print statistics
β”‚   β”‚   β”œβ”€β”€ tool_change.h/cpp    # Multi-extruder switching
β”‚   β”‚   β”œβ”€β”€ ft_motion/           # Fine-tune motion
β”‚   β”‚   └── stepper/             # Stepper internals, Trinamic
β”‚   β”œβ”€β”€ feature/                 # 80+ optional features
β”‚   β”‚   β”œβ”€β”€ bedlevel/            # UBL, MBL, ABL
β”‚   β”‚   β”œβ”€β”€ leds/                # LED color control
β”‚   β”‚   β”œβ”€β”€ mmu/                 # Multi-material unit
β”‚   β”‚   β”œβ”€β”€ mmu3/                # MMU3 variant
β”‚   β”‚   β”œβ”€β”€ powerloss.h/cpp      # Power loss recovery
β”‚   β”‚   β”œβ”€β”€ runout.h/cpp         # Filament runout detection
β”‚   β”‚   β”œβ”€β”€ pause.h/cpp          # Pause/resume
β”‚   β”‚   β”œβ”€β”€ mixing.h/cpp         # Mixed extruder
β”‚   β”‚   β”œβ”€β”€ fwretract.h/cpp      # Firmware retraction
β”‚   β”‚   β”œβ”€β”€ resonance/           # Resonance compensation
β”‚   β”‚   β”œβ”€β”€ spindle_laser.h/cpp  # Spindle/laser control
β”‚   β”‚   β”œβ”€β”€ ethernet.h/cpp       # Ethernet connectivity
β”‚   β”‚   β”œβ”€β”€ solenoid.h/cpp       # Solenoid control
β”‚   β”‚   β”œβ”€β”€ password/            # Password protection
β”‚   β”‚   β”œβ”€β”€ joystick.h/cpp       # Joystick input
β”‚   β”‚   β”œβ”€β”€ tmc_util.h/cpp       # TMC driver utilities
β”‚   β”‚   └── ...                  # 60+ more features
β”‚   β”œβ”€β”€ lcd/                     # Display/UI subsystem
β”‚   β”‚   β”œβ”€β”€ marlinui.h/cpp        # Main UI controller
β”‚   β”‚   β”œβ”€β”€ HD44780/             # Hitachi HD44780 LCD
β”‚   β”‚   β”œβ”€β”€ dogm/                # DOGM OLED/LCD
β”‚   β”‚   β”œβ”€β”€ tft/                 # TFT displays
β”‚   β”‚   β”œβ”€β”€ tft_io/              # TFT I/O drivers
β”‚   β”‚   β”œβ”€β”€ dwin/                # DWIN displays
β”‚   β”‚   β”œβ”€β”€ extui/               # Extensible UI (MKS LVGL)
β”‚   β”‚   β”œβ”€β”€ menu/                # Menu system
β”‚   β”‚   β”œβ”€β”€ touch/               # Touch screen
β”‚   β”‚   β”œβ”€β”€ language/            # Multi-language strings
β”‚   β”‚   └── sovol_rts/           # Sovol RTS display
β”‚   β”œβ”€β”€ libs/                    # Utility libraries
β”‚   β”‚   β”œβ”€β”€ bresenham.h          # Bresenham line algorithm
β”‚   β”‚   β”œβ”€β”€ vector_3.h/cpp       # 3D vector math
β”‚   β”‚   β”œβ”€β”€ circularqueue.h      # Generic circular queue
β”‚   β”‚   β”œβ”€β”€ adc/                 # ADC utilities
β”‚   β”‚   β”œβ”€β”€ heatshrink/          # Decompression
β”‚   β”‚   β”œβ”€β”€ nozzle.cpp/h         # Nozzle cleaning
β”‚   β”‚   β”œβ”€β”€ numtostr.h/cpp       # Number-to-string
β”‚   β”‚   β”œβ”€β”€ hex_print.h/cpp      # Hex printing
β”‚   β”‚   β”œβ”€β”€ crc16.h/cpp          # CRC-16 calculation
β”‚   β”‚   β”œβ”€β”€ stopwatch.h/cpp      # Stopwatch utility
β”‚   β”‚   β”œβ”€β”€ least_squares_fit.h  # Least squares fitting
β”‚   β”‚   └── ...                  # 15+ utility libs
β”‚   β”œβ”€β”€ sd/                      # SD card subsystem
β”‚   β”‚   β”œβ”€β”€ cardreader.h/cpp     # Card reader interface
β”‚   β”‚   β”œβ”€β”€ SdFat*               # SdFat library (file system)
β”‚   β”‚   β”œβ”€β”€ disk_io_driver.h     # Disk I/O abstraction
β”‚   β”‚   └── usb_flashdrive/      # USB flash drive support
β”‚   β”œβ”€β”€ pins/                    # Pin definitions (400+ files)
β”‚   β”‚   β”œβ”€β”€ pins.h               # Pin inclusion router
β”‚   β”‚   β”œβ”€β”€ ramps/               # Ramps board family
β”‚   β”‚   β”œβ”€β”€ mega/                # Mega board family
β”‚   β”‚   β”œβ”€β”€ rambo/               # Rambo board family
β”‚   β”‚   β”œβ”€β”€ sanguino/            # Sanguino board family
β”‚   β”‚   β”œβ”€β”€ stm32f1/             # STM32F1 boards
β”‚   β”‚   β”œβ”€β”€ stm32f4/             # STM32F4 boards
β”‚   β”‚   β”œβ”€β”€ stm32f7/             # STM32F7 boards
β”‚   β”‚   β”œβ”€β”€ stm32h7/             # STM32H7 boards
β”‚   β”‚   β”œβ”€β”€ stm32g0/             # STM32G0 boards
β”‚   β”‚   β”œβ”€β”€ stm32f0/             # STM32F0 boards
β”‚   β”‚   β”œβ”€β”€ sam/                 # SAM boards
β”‚   β”‚   β”œβ”€β”€ samd/                # SAMD boards
β”‚   β”‚   β”œβ”€β”€ rp2040/              # RP2040 boards
β”‚   β”‚   β”œβ”€β”€ lpc1768/             # LPC1768 boards
β”‚   β”‚   β”œβ”€β”€ lpc1769/             # LPC1769 boards
β”‚   β”‚   β”œβ”€β”€ teensy2/             # Teensy 2.x boards
β”‚   β”‚   β”œβ”€β”€ teensy3/             # Teensy 3.x boards
β”‚   β”‚   β”œβ”€β”€ teensy4/             # Teensy 4.x boards
β”‚   β”‚   β”œβ”€β”€ esp32/               # ESP32 boards
β”‚   β”‚   β”œβ”€β”€ gd32f1/              # GD32F1 boards
β”‚   β”‚   β”œβ”€β”€ gd32f3/              # GD32F3 boards
β”‚   β”‚   β”œβ”€β”€ hc32f4/              # HC32F4 boards
β”‚   β”‚   β”œβ”€β”€ at32f4/              # AT32F4 boards
β”‚   β”‚   └── native/              # Native/simulator
β”‚   β”œβ”€β”€ HAL/                     # Hardware Abstraction Layer
β”‚   β”‚   β”œβ”€β”€ HAL.h                # HAL interface definition
β”‚   β”‚   β”œβ”€β”€ platforms.h          # Platform selection
β”‚   β”‚   β”œβ”€β”€ shared/              # Cross-platform HAL code
β”‚   β”‚   β”‚   β”œβ”€β”€ HAL.cpp/h        # Shared HAL implementation
β”‚   β”‚   β”‚   β”œβ”€β”€ Delay.h          # Safe delay function
β”‚   β”‚   β”‚   β”œβ”€β”€ eeprom_api.h     # EEPROM API
β”‚   β”‚   β”‚   β”œβ”€β”€ cpu_exception/   # Exception handling
β”‚   β”‚   β”‚   └── backtrace/       # Stack backtrace
β”‚   β”‚   β”œβ”€β”€ STM32/               # STM32 platform HAL
β”‚   β”‚   β”œβ”€β”€ AVR/                 # AVR platform HAL
β”‚   β”‚   β”œβ”€β”€ ESP32/               # ESP32 platform HAL
β”‚   β”‚   β”œβ”€β”€ DUE/                 # Arduino Due HAL
β”‚   β”‚   β”œβ”€β”€ SAMD21/              # SAMD21 HAL
β”‚   β”‚   β”œβ”€β”€ SAMD51/              # SAMD51 HAL
β”‚   β”‚   β”œβ”€β”€ RP2040/              # RP2040 HAL
β”‚   β”‚   β”œβ”€β”€ LPC1768/             # LPC1768 HAL
β”‚   β”‚   β”œβ”€β”€ GD32_MFL/            # GD32 HAL
β”‚   β”‚   β”œβ”€β”€ HC32/                # HC32 HAL
β”‚   β”‚   β”œβ”€β”€ AT32/                # AT32 HAL
β”‚   β”‚   β”œβ”€β”€ TEENSY31_32/         # Teensy 3.1/3.2 HAL
β”‚   β”‚   β”œβ”€β”€ TEENSY35_36/         # Teensy 3.5/3.6 HAL
β”‚   β”‚   β”œβ”€β”€ TEENSY40_41/         # Teensy 4.0/4.1 HAL
β”‚   β”‚   β”œβ”€β”€ STM32F1/             # STM32F1 HAL
β”‚   β”‚   β”œβ”€β”€ LINUX/               # Linux simulator HAL
β”‚   β”‚   └── NATIVE_SIM/          # Native simulator HAL
β”‚   └── tests/                   # Unit tests
β”‚       β”œβ”€β”€ unit_tests.h/cpp     # Test suite
β”‚       └── *.ini                # Test configurations
β”œβ”€β”€ docs/                        # Project documentation
β”‚   β”œβ”€β”€ AGENTS.md                # This document
β”‚   └── diagrams/                # Architecture diagrams
β”‚       β”œβ”€β”€ high-level-architecture.drawio
β”‚       β”œβ”€β”€ processing-pipeline.drawio
β”‚       └── component-relationships.drawio
β”œβ”€β”€ buildroot/                   # Build infrastructure
β”‚   β”œβ”€β”€ share/PlatformIO/        # PlatformIO board definitions & scripts
β”‚   β”œβ”€β”€ test-gcode/              # G-code test files
β”‚   └── tests/                   # Build test configurations
β”œβ”€β”€ ini/                         # PlatformIO platform configs
β”‚   β”œβ”€β”€ avr.ini, due.ini, esp32.ini
β”‚   β”œβ”€β”€ stm32-common.ini, stm32f1.ini, stm32f4.ini
β”‚   β”œβ”€β”€ stm32f7.ini, stm32h7.ini, stm32g0.ini
β”‚   β”œβ”€β”€ samd21.ini, samd51.ini
β”‚   β”œβ”€β”€ raspberrypi.ini, teensy.ini
β”‚   β”œβ”€β”€ at32.ini, gd32.ini, hc32.ini
β”‚   β”œβ”€β”€ lpc176x.ini, native.ini
β”‚   β”œβ”€β”€ features.ini, renamed.ini
β”‚   └── stm32f1-maple.ini
β”œβ”€β”€ test/                        # Root-level test configurations
β”œβ”€β”€ docker/                      # Docker build environment
β”œβ”€β”€ .github/workflows/           # CI/CD pipelines
└── platformio.ini               # Main PlatformIO configuration
```

## 11. Constructing a Pull Request

Marlin accepts AI-assisted code (see `.github/contributing.md`). It must be sensible and reviewable. Follow these rules when preparing a PR.

### Scope and size

- **One PR, one purpose.** A PR should be a single self-contained change that builds and passes CI on its own.
- **Split large changes.** If a change touches several unrelated areas, or is large enough that a reviewer can't hold it in their head, split it into two (or more) smaller PRs. Typical splits: refactor first, feature second; core logic first, UI/LCD support second; one HAL or board family per PR; sanity checks and docs with the feature they cover.
- **Order dependent PRs.** If PR B needs PR A, say so in B's description and don't open B until A is far enough along to be reviewed.
- **No drive-by changes.** Don't reformat, rename, or tidy code you aren't changing. Keep the diff minimal.
- **Don't change defaults** in `Configuration.h` / `Configuration_adv.h` unless that is the purpose of the PR. New features are disabled by default.

### Before you start

- Branch from the latest `bugfix-2.1.x` (the working branch). Never target release branches.
- We occasionally backport fixes to lts-* branches. Very small non-duplicate patches are accepted.
- Read the neighboring code and follow its conventions. Check `buildroot/skills/` for step-by-step procedures.
- Read the HAL-specific `AGENTS.md` (`Marlin/src/HAL/<FAMILY>/AGENTS.md`) when touching a HAL.

### Making the change

- Code must compile on 8-bit AVR and 32-bit targets. Mind flash and RAM on AVR. Keep the base build requirements from growing.
- Gate optional code with `ENABLED()` / `DISABLED()` / `ANY()` / `NONE()` / etc. and add validation to `Marlin/src/inc/SanityCheck.h`.
- Use a suitable insertion point for Configuration and Conditionals. They follow a strict order set by `Marlin/src/inc/MarlinConfig.h`.
- Don't hardcode pins; use the pin headers in `src/pins`.
- When adding or changing a user-facing option, update its comments in `Configuration*.h` and note any `Conditionals`, `Warnings.cpp`, or `config.ini` impacts.
- Follow the Marlin coding standards (2-space indent, no tabs, spacing as in nearby code). Indent new code similar to surroundings (including preprocessor nesting) and avoid auto-formatters.

### Verifying

- Use `MarlinSimUI` for direct testing in a simulated environment with a rich MCP interface. (And contribute your enhancements to `MarlinSimUI`.)
- Build at least one affected environment (`buildroot/bin/mftest`; see the `marlin-build-test` skill).
- **Add tests with new features and options.** Add or update a `buildroot/tests/<env>/config-NN.ini` build test so CI exercises the feature, along with its dependent options.
- Add a unit test in `Marlin/tests/<area>/` (run with `make unit-test-all-local`) when the logic can be checked without hardware.
  - Bug fixes should get a test when one can catch the regression. See the `marlin-build-test` skill.
- Report honestly what was and wasn't tested. Never claim a build or test passed unless you ran it.

### Commit messages and PR description

- Imperative mood, first line of 72 characters or fewer, prefixed with a gitmoji-style emoji as in `git log` (e.g. πŸ› fix, ✨ feature, ⚑️ performance, πŸ”§ config, 🩹 minor fix, πŸ§‘β€πŸ’» developer tooling, 🚸 UX).
- Don't put issue numbers in the PR title. Reference them in the description.
- Fill in every section of `.github/pull_request_template.md`: Description, Requirements, Benefits, Configurations, Related Issues.
- Keep history clean: rebase on `bugfix-2.1.x` rather than merging, and squash fixups into the commits they belong to.

### Skills

Reusable procedures for contributors and their tools live in `buildroot/skills/`. Each skill is a folder with a `SKILL.md`. See `buildroot/skills/README.md`.