Skip to content

Latest commit

 

History

44 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OSIX Firmware

Высокопроизводительная модульная прошивка для 3D-принтера на ESP32-S3-N16R8, написанная на Rust поверх стека ESP-IDF (esp-idf-sys / esp-idf-hal / esp-idf-svc + FreeRTOS). esp-hal не используется.

Статус: Этап 11 / 11 — финальная сборка App (все этапы завершены)

Все 11 этапов реализованы. Прошивка компилируется (по построению, см. оговорку о верификации ниже) в единое целое: App инициализирует плату, собирает реальные драйверы моторов (Tmc2209Driver X/Y, Uln2003Driver Z) из пинов Board, контуры температуры (термисторы на ADC1, нагреватели и вентилятор на ШИМ через LEDC), планировщик движения и G-Code исполнитель поверх USB CDC — и запускает главный цикл.

Что добавлено на этапе 11

Файл Содержимое
src/hal_adapters.rs EspAdcThermistor (классический драйвер adc1_*), EspLedcPwm (безопасная обёртка esp_idf_hal::ledc) — единственное место, где абстрактные трейты подсистем встречаются с конкретным железом
src/hardware_build.rs build_printer_state/build_axes/build_temperature_controller/build_endstop_set — собирает Tmc2209Driver/Uln2003Driver/Heater/Fan/EndstopSet из пинов Board и конфигурации
src/printer_state.rs PrinterState — конкретная реализация PrinterContext: маршрутизация к MotionPlanner/TemperatureController/SettingsManager, хоуминг, блокирующее ожидание температуры
src/app.rs App — жизненный цикл прошивки и главный кооперативный цикл (USB G-Code → прокачка движения → регулирование температуры → watchdog/E-Stop)

Архитектурные решения этапа 11

  • Главный цикл — однопоточный и кооперативный, сознательно. Все примитивы для полноценной многозадачности уже написаны и протестированы (scheduler::Task/TaskPriority, network::*, sdcard::PrintJob), но для первой интегрированной версии выбрана простая, предсказуемая и проверяемая схема: один поток обрабатывает USB, прокачивает очередь движения и регулирует температуру по очереди. Перенос на отдельные задачи FreeRTOS (TaskPriority::StepGenerator для генератора шагов, TaskPriority::GCode для приёма USB) — это последующее расширение, которое не потребует изменений в PrinterState/GcodeExecutor, только в App::run.
  • Board::init() вызывается ровно один раз и сразу разбирается на части: power/watchdog/rgb остаются у App напрямую для главного цикла, а pins/uart1/uart2/ledc уходят в build_printer_state. Попытка вызвать Board::init() дважды была бы ошибкой (Peripherals::take() — не более одного раза за время жизни программы) — этот момент был сознательно проверен при проектировании App::new().
  • SD-карта и сеть — не вписаны в главный цикл этой сборки. sdcard/network полностью реализованы, протестированы на хосте и готовы к подключению, но их проводка (SPI-шина уже частично занята SD-картой по распиновке, Wi-Fi требует EspSystemEventLoop+раздел NVS, HTTP/WebSocket — отдельные задачи) — это следующий, самостоятельный шаг расширения App, а не часть этой финальной сборки, ограниченной базовым циклом печати через USB.
  • Резервный ток TMC2209 (800 мА / 300 мА) — разумное значение по умолчанию, не из конфигурации. motion.toml (этап 1) не содержит отдельного поля тока на ось; жёстко заданное в hardware_build.rs значение подходит для типового NEMA17, но должно стать частью AxisMotionConfig в одной из последующих итераций, если потребуется тонкая настройка под конкретные двигатели.

Честная оговорка о верификации (относится ко всему проекту)

Прошивка написана и вычитана вручную по документации и памяти о реальных сигнатурах esp-idf-hal/esp-idf-svc/esp-idf-sys для версий, указанных в .cargo/config.toml (ESP_IDF_VERSION = v5.2.1) и Cargo.toml. В песочнице, где эта прошивка была написана, нет ни сети, ни установленного Xtensa-тулчейна ESP-IDF, поэтому ни разу не был выполнен реальный cargo build для целевой платформы. Каждый файл спроектирован так, чтобы бизнес-логика (планировщик, кинематика, ПИД, парсер G-Code, интерполяция шагов, протокол USB) была полностью безопасна и покрыта хостовыми unit-тестами независимо от конкретных HAL-обёрток — но сама проводка конкретного железа в hardware_build.rs/hal_adapters.rs (в первую очередь ADC1, LEDC, UART, SPI, TinyUSB, SDSPI, SPIFFS) должна быть проверена первой реальной сборкой (cargo build --release, см. раздел «Сборка» ниже) — несовпадения в именах полей/функций сгенерированных bindgen-биндингов между версиями esp-idf-sys являются наиболее вероятным источником ошибок компиляции, и они будут точечными (компилятор укажет на конкретное поле/функцию), а не системными.

Модули, полностью реализованные, но не подключённые к главному циклу

Модуль Готовность Что нужно для подключения
src/scheduler/* Полностью реализован и протестирован Заменить App::run's кооперативный цикл на отдельные Task::spawn с TaskPriority
src/sdcard/* Полностью реализован и протестирован Отдельная инициализация SPI-шины SD-карты, вызов PrintJob::next_command() вместо/вместе с USB в главном цикле
src/network/* Полностью реализован и протестирован EspSystemEventLoop, раздел NVS, отдельные задачи для HTTP/WebSocket

Полный состав проекта (все 11 этапов)

Модуль Содержимое
Cargo.toml, build.rs, .cargo/config.toml, rust-toolchain.toml Сборочная конфигурация под xtensa-esp32s3-espidf
sdkconfig.defaults, partitions.csv PSRAM (Octal, 8 MB), Flash 16 MB, TWDT, Wi-Fi, USB CDC, FATFS, settings (SPIFFS), ota_0/ota_1
src/error.rs, src/types.rs Единый AppError, общие типы
src/board/* Распиновка (включая термисторы/нагреватели/вентилятор), питание/E-Stop, Task Watchdog, статусный WS2812
src/config/* printer.toml/motion.toml/network.toml/temperature.toml
src/drivers/motor/* MotorDriver, Axis/AxisControl, Tmc2209Driver, Uln2003Driver
src/motion/* Kinematics, MotionPlanner (look-ahead), TrapezoidProfile, StepGenerator
src/scheduler/* Task (приоритеты FreeRTOS), PeriodicTimer
src/gcode/*, src/endstops/* Парсер, PrinterContext, все команды из ТЗ, концевики
src/temperature/* Термистор, ПИД с автонастройкой, Heater с thermal runaway, Fan
src/storage/* SettingsManagerM500/M501
src/sdcard/* SdCard, PrintJob — печать с карты памяти
src/usb/* SerialConsole — протокол ok/Error: ... поверх USB CDC
src/network/* WifiManager, HttpApiServer, TelemetryBroadcaster, OtaUpdater
src/system/* CPU/память, паника, причина сброса
src/hal_adapters.rs, src/hardware_build.rs, src/printer_state.rs, src/app.rs Финальная сборка: конкретное железо → PrinterState → главный цикл

Архитектурные решения этого этапа

  • Абстракция от распиновки. Все номера GPIO собраны в board::pins::PinMap. Драйверы (следующий этап) получают уже сконфигурированные периферийные объекты, а не читают номера пинов напрямую — замена платы не потребует правок в логике.
  • unsafe изолирован. Единственные места с unsafe: board/watchdog.rs (прямые вызовы esp_task_wdt_*, которых нет в безопасных обёртках esp-idf-hal/esp-idf-svc) и создание GPIO-пинов по номеру в board/mod.rs (AnyOutputPin::new / AnyIOPin::new — сознательно небезопасная операция самого esp-idf-hal, обходящая систему владения Peripherals, чтобы не тащить в Board десятки индивидуально типизированных полей GPIO). Остальной код — safe Rust.
  • Периферия резервируется заранее. Peripherals::take() вызывается ровно один раз, в Board::init(). Ещё не задействованные ресурсы (UART1, UART2, SPI2 — под TMC2209 и SD-карту) сохраняются как публичные поля Board, чтобы модули drivers и storage на следующих этапах могли их получить, не переписывая инициализацию платы.
  • Конфигурация не знает про хранилище. config::AppConfig умеет парситься из TOML-строк и сериализоваться обратно, но не знает, откуда берутся эти строки (SD-карта, NVS, SPIFFS-раздел settings) — это подключит модуль storage без изменения config.

Важная оговорка о проверке компиляции

В текущей среде генерации кода недоступны сеть и установленный Xtensa-toolchain ESP-IDF, поэтому запустить cargo build --release для реальной цели xtensa-esp32s3-espidf здесь невозможно — код написан и вычитан вручную с учётом актуальных сигнатур esp-idf-hal 0.44 / esp-idf-svc 0.49, но перед прошивкой в железо обязательно выполните первую сборку локально (см. ниже) и сообщите, если компилятор укажет на несоответствие версий API — это будет исправлено в следующей итерации.

Сборка

Требуется установленный espup (тулчейн Xtensa Rust) и ldproxy/espflash:

espup install
. $HOME/export-esp.sh

cargo install ldproxy espflash

cd printer-fw
cargo build --release
cargo espflash flash --release --monitor

Первая сборка вызовет embuild, который скачает и соберёт сам ESP-IDF (версия закреплена в .cargo/config.toml, ESP_IDF_VERSION = "v5.2.1") — это может занять продолжительное время.

Дальнейшие этапы (план)

  1. Каркас проекта, board support, конфигурация ✅ (этот коммит)
  2. Абстракция MotorDriver + драйверы Tmc2209Driver и Uln2003Driver (регистры TMC2209 отдельными структурами, UART-протокол, микрошаг/ток/ StealthChop/SpreadCycle/CoolStep/StallGuard)
  3. motion: планировщик, очередь, ускорение/торможение, jerk, junction deviation, look-ahead, генератор шагов; кинематика Cartesian
  4. gcode: парсер и исполнитель (G0/G1/G4/G28/G90/G91/G92, M17/M18, M104/M105/M106/M107/M109/M114/M115/M119/M140/M190/M500/M501)
  5. temperature: термисторы, PID, thermal runaway, автонастройка PID
  6. storage: персистентные настройки (SPIFFS-раздел settings)
  7. sdcard: SPI + FAT32, печать с карты
  8. usb: CDC Serial
  9. network: Wi-Fi, HTTP API, WebSocket, OTA
  10. system: диагностика CPU/памяти, обработчик паники, управление сбросом

Каждый этап будет содержать дерево проекта, полный код новых файлов и описание того, как он стыкуется с уже написанными модулями.

About

custom firmware for a homemade printer

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages