Files
IR-protocol/ref/IR_DMA_TX_backend.md

4.4 KiB
Raw Blame History

Контракт бэкенда DMA-TX ИК (IrDmaTxStm32)

См. также: IR_TX_MODES.md — общая схема выбора legacy ISR, buffered ISR и external backend.

Платформа: STM32G4, Arduino STM32. Передача: DMA memory → GPIO BSRR, запрос от TIM UPDATE (частота carrierFrec×2 из IR_Encoder::beginClockOnly).

Число потоков (шаблон)

Класс: IrDmaTxStm32<MaxStreams>. Число слотов в Config::streams[] и внутреннем массиве задаётся в коде, без -D и без макроса до инклюда:

constexpr size_t kStreams = 2;
static IrDmaTxStm32<kStreams> dma;
IrDmaTxStm32<kStreams>::Config cfg;
// IRQ: IrDmaTxStm32<kStreams>::instance()

По умолчанию: IrDmaTxStm32<> эквивалентно IrDmaTxStm32<irproto::kDefaultDmaTxMaxStreams> (IR_config.h, обычно 4). Реализация в заголовке (отдельного .cpp нет).

Роль библиотеки

  • Разбор пакета в RLE-пробеги: IR_Encoder::buildGateRuns.
  • Генерация слов для BSRR (несущая/тишина по тикам), предзаполнение буфера и дозаполнение по прерываниям half/complete.
  • Настройка канала DMA, DMAMUX, кольцевой режим, старт/стоп DMA и таймера, колбэки HAL.
  • В begin() только HAL_NVIC_EnableIRQ для каналов DMA (без SetPriority).

Роль прошивки (клиента)

Буферы и размеры

На каждый поток в StreamCfg клиент передаёт:

Поле Смысл
dmaWords Указатель на массив uint32_t — слова для записи в BSRR.
dmaWordCount Число слов (32-bit), чётное, ≥ 2. Половина — один «полубуфер» для HT/TC IRQ.
gateRuns Массив IR_Encoder::IR_TxGateRun для выхода buildGateRuns.
maxGateRuns Длина этого массива. Должен быть достаточен для самого длинного кадра.

Память и выравнивание — ответственность клиента; типичные порядки: 4096 слов DMA, 1024 ранов (как в машинке).

Таймер и DMA

  • HardwareTimer / тот же TIM, что и beginClockOnly, без конкурирующего attachInterrupt на UPDATE.
  • instance, irq, dmamuxRequest (например DMA_REQUEST_TIM17_UP) — из схемы платы; оба потока на одном TIM обычно используют один TIMx_UP в DMAMUX.

Приоритеты NVIC

Не задаются в библиотеке. После begin() клиент выставляет preempt/sub для DMA1_ChannelN (и согласует с приёмом EXTI и др.), например общей функцией вроде Car_applyInterruptPriorities().

Прерывания DMA

Библиотека не объявляет DMA1_ChannelN_IRQHandler. В одном .cpp прошивки — единственное определение на канал, внутри:

IrDmaTxStm32<N>::instance()->irqForStream(i) (тот же N, что у объекта бэкенда) или IrDmaTxStm32_onDmaHandle(hdma).

Контракт IR_Encoder::setExternalTxBackend

Подключение: setExternalTxBackend(startFn, busyFn, ctx).

  • startFn(ctx, enc, packet, len) — должен вызвать IrDmaTxStm32<N>::start(enc, packet, len) (или обёртку). Возвращает успех старта DMA.
  • busyFn(ctx) — пока возвращает «занято», новая отправка не стартует. У IrDmaTxStm32<N>::busy(): true, если все настроенные потоки в передаче (для двух передатчиков — оба активны); иначе можно запустить второй канал.

Сбой begin()

При ошибке HAL_DMA_Init и т.п. begin() возвращает false, instance() не используется для IRQ до успешного begin().