From 96ffb91b971302ba8edc080a1ef704967587cefd Mon Sep 17 00:00:00 2001 From: DashyFox Date: Tue, 11 Aug 2026 18:33:07 +0300 Subject: [PATCH] =?UTF-8?q?fix(tx):=20=D0=BF=D1=80=D0=B8=D0=BE=D1=80=D0=B8?= =?UTF-8?q?=D1=82=D0=B5=D1=82=20IRQ=20DMA-TX=20=D1=8F=D0=B2=D0=BD=D0=BE=20?= =?UTF-8?q?=D0=BD=D0=B8=D0=B6=D0=B5=20SysTick/EXTI=20=E2=80=94=20millis()?= =?UTF-8?q?=20=D0=B7=D0=B0=D0=BC=D0=B5=D0=B4=D0=BB=D1=8F=D0=BB=D1=81=D1=8F?= =?UTF-8?q?=20=D0=BF=D0=BE=D0=B4=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B4=D0=B0?= =?UTF-8?q?=D1=87=D0=B5=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HAL_NVIC_EnableIRQ без SetPriority оставлял DMA-каналы TX на приоритете 0 (уровень SysTick на G4). Длинный refill кольца BSRR (полубуфер 2048 слов = ~3.3мс при HCLK 12МГц) не вытеснялся, тики SysTick слипались: millis() замедлялся в 1.6x (один излучатель) / 2.2x (два) на всё время передачи. На машинке это ~37% вранья часов в каждый ИК-кадр: PID dt, планировщик, тайминги протокола. Мерено на стенде TofSickHunt 2026-08-11 (Car raw/idle_cur_vs_coup*): прогоны «60с» шли 85-95 реальных секунд. Фикс: irproto::kDmaTxIrqPriority=8 — ниже EXTI приёмника (6), выше дна; SysTick честный. ISR-TX путь (F401/КУ) не подвержен: его refill на TIM-приоритете 14. Верификация дилатации на стенде — раунд 4 (прерван, перезапустить). Co-Authored-By: Claude Fable 5 --- IR_config.h | 7 +++++++ IrDmaTxStm32.h | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/IR_config.h b/IR_config.h index afdfff5..31f439e 100644 --- a/IR_config.h +++ b/IR_config.h @@ -6,6 +6,13 @@ /** Число потоков DMA-TX задаётся шаблоном: IrDmaTxStm32<2>, см. IrDmaTxStm32.h и irproto::kDefaultDmaTxMaxStreams. */ namespace irproto { constexpr size_t kDefaultDmaTxMaxStreams = 4U; +/** NVIC-приоритет IRQ DMA-каналов TX (refill кольца BSRR-слов). Refill длинный (полубуфер + * 2048 слов = миллисекунды на небыстрых SYSCLK), а его дедлайн мягкий (~9 мс при 38кГц×6), + * поэтому он обязан сидеть НИЖЕ SysTick (0) и EXTI приёмника (6): с приоритетом по умолчанию + * (0, HAL_NVIC_EnableIRQ без SetPriority) он не вытеснялся SysTick'ом, тики слипались и + * millis() замедлялся в 1.6×/2.2× (один/два потока) на всё время передачи — мерено на стенде + * TofSickHunt 2026-08-11. Меньше число = выше приоритет; 8 = ниже EXTI, выше самого дна. */ +constexpr uint32_t kDmaTxIrqPriority = 8U; /** Кольцевой буфер BSRR-слов для ISR-TX (как у DMA: два полублока). Чётное число. */ constexpr uint16_t kIsrTxBsrrWordCount = 256U; /** Максимум RLE-сегментов для buildGateRuns при ISR-TX. */ diff --git a/IrDmaTxStm32.h b/IrDmaTxStm32.h index 2e71fe2..3ef0549 100644 --- a/IrDmaTxStm32.h +++ b/IrDmaTxStm32.h @@ -87,6 +87,10 @@ public: s_instance = this; for (uint8_t i = 0; i < streamCount_; i++) { + // Приоритет ЯВНО и ДО включения: без SetPriority канал остаётся на 0 (уровень + // SysTick), длинный refill не вытесняется и глотает тики millis. Обоснование + // и измерения — у irproto::kDmaTxIrqPriority (IR_config.h). + HAL_NVIC_SetPriority(streams_[i].dmaIrq, irproto::kDmaTxIrqPriority, 0); HAL_NVIC_EnableIRQ(streams_[i].dmaIrq); }