Перейти до змісту

Features та налаштування

Тут є два різних рівні. Features визначають, який код взагалі потрапить у збірку. Configuration задає параметри вже обраної реалізації під час запуску. Якщо ввімкнути async, а потім передати іншу частоту SPI, blocking-дисплеєм він від цього не стане.

Що вмикається за замовчуванням

У самого SDK defaults такі: alloc, blocking, RefCellBus, display_buffer_8192.

Для прикладів ми зазвичай пишемо default-features = false і явно перелічуємо потрібне. Це особливо важливо для async: додавання одного async до defaults залишить ще й blocking, а така комбінація заборонена.

Blocking чи async

blocking простіший для першого меню або маленького застосунку. Операція SPI виконується до завершення, а потім код іде далі. Для кнопок і кількох написів цього часто цілком достатньо.

async додає Embassy та esp-rtos, а операції, які можуть чекати, отримують .await. Для нього потрібен AsyncBus. Повний async-приклад показує й точку входу, й запуск задачі, й виведення на дисплей.

Bus, тобто спільна SPI-шина

Дисплей і microSD використовують один SPI2, але різні CS. Обидва драйвери не можуть одночасно відправляти свої байти, тому SDK обгортає шину відповідним способом.

  • RefCellBus — blocking з одним контекстом виконання. Конфліктні позики ловляться під час виконання.
  • CriticalSectionBus — blocking із критичною секцією. Довгі SPI-операції можуть затримувати обробку інших переривань.
  • AsyncBus — для async-конфігурації, з асинхронним mutex.
  • AtomicBus — feature існує, але поточний SD-адаптер його не підтримує. Цю конфігурацію зараз не обирайте.

Рівно один тип шини за раз. Наявність слова mutex також не робить довільні операції у перериванні хорошою ідеєю: зчитування великого файла краще робити у звичайному коді або задачі.

display_buffer

Варіанти: display_buffer_512, display_buffer_1024, display_buffer_8192. Оберіть один. Для blocking-дисплея це робочий буфер передачі драйвера mipidsi, а не повний кадр.

Повний кадр 280×240 у RGB565 займає 134400 байтів незалежно від цього feature. Async-дисплей працює через lcd-async; розмір власного буфера пікселів у застосунку задаєте ви. У прикладі це тільки смуга 280×24.

Alloc

Feature alloc підключає esp-alloc, але резервувати й ініціалізувати heap треба у своїй точці входу:

esp_alloc::heap_allocator!(size: 16 * 1024);

Робіть це до коду, який може виділяти пам'ять. Vec, String зі стандартного alloc і радіостек можуть її потребувати. heapless::String<N> має фіксований буфер у самому об'єкті.

Не плутайте три речі: бібліотеку Rust alloc, feature SDK з такою самою назвою та фактичний heap. Вимкнення feature SDK прибирає його опціональну залежність esp-alloc, але не прибирає extern crate alloc з іншого крейта.

Саме так поводиться SD-драйвер async-embedded-sdmmc 0.3.1: безумовно підключає alloc, через що кінцева прошивка потребує глобального allocator. Це вимога компонування поточної залежності, а не доказ динамічних алокацій під час роботи з картою. FAT-бібліотека embedded-sdmmc 0.9.0 heap не потребує. Наші 16 КіБ — зручний початковий розмір прикладів, а не обов'язкова витрата SD; подробиці — пам'ять та SD.

Radio та RTC

radio додає ESP-радіостек і залежності для Wi-Fi/BLE, а також allocator та RTOS. Самого feature недостатньо для підключення: ще потрібні конфігурація мережі або BLE-логіка, обробка з'єднання та відповідні задачі. Для навчальних прикладів без радіо він не потрібен.

keira-rtc — окремий необов'язковий feature. Він дає keira_rtc::KeiraClock, не додаючи радіо чи нових залежностей. Джерело — збережений RTC після програмного перезапуску з Keira, а результат — UTC timestamp. Умови й повний код є на сторінці RTC.

Configuration

Після features налаштовуємо сам пристрій:

use lilkaoxide::prelude::*;

let mut config = Configuration::default();
config.buzzer_config.duty_pct = 0;
config.spi_frequency /= 3;
// У blocking-прошивці:
let lilka = Lilka::init(config).expect("Lilka init failed");

Так зумер не почне пищати одразу, а SPI буде 20 МГц замість 60. Для async останній виклик потребує .await.

Інші поля: cpu_clock, поворот дисплея display_rotation, порядок оновлення display_refresh_order, tearing-сигнал display_tearing, параметри ADC adc_cfg та I2S i2s_tx_config. Змінюйте тільки потрібне, а решту залишайте через Configuration::default().

У blocking поворот задається типом з mipidsi::options, в async — з lilkaoxide::lcd_async::options. Назва Rotation однакова, але типи різні. Штатний Deg270 дає 280×240; після іншого повороту потрібно перерахувати розміри власних буферів та координати.