| 557 | } |
| 558 | |
| 559 | void RmtMemoryManager::free(u8 channel_id, bool is_tx) FL_NOEXCEPT { |
| 560 | #if FASTLED_RMT_STATIC_ALLOCATION |
| 561 | // Static-allocation mode: the user has asserted no removeLeds() / late |
| 562 | // addLeds(). The destructor still calls free() at process end but the |
| 563 | // ledger isn't meaningfully tracked, so erasing from the allocations |
| 564 | // vector + emitting the FL_LOG_RMT diagnostic is dead work. Skipping it |
| 565 | // lets the linker drop fl::vector_inlined::erase + the diagnostic |
| 566 | // operator<< chain. See #2856 item 3.6. |
| 567 | (void)channel_id; |
| 568 | (void)is_tx; |
| 569 | #else |
| 570 | ChannelAllocation* alloc = findAllocation(channel_id, is_tx); |
| 571 | if (!alloc) { |
| 572 | FL_WARN("RMT " << (is_tx ? "TX" : "RX") << " channel " |
| 573 | << static_cast<int>(channel_id) << " not found in allocations"); |
| 574 | return; |
| 575 | } |
| 576 | |
| 577 | // Free words from appropriate pool (DMA channels have 0 words, so this is safe) |
| 578 | freeWords(alloc->words, is_tx); |
| 579 | |
| 580 | FL_LOG_RMT("RMT " << (is_tx ? "TX" : "RX") << " channel " |
| 581 | << static_cast<int>(channel_id) << " freed: " << alloc->words << " words" |
| 582 | << (alloc->is_dma ? " (DMA)" : "")); |
| 583 | |
| 584 | // Remove from allocations vector |
| 585 | for (auto it = mLedger.allocations.begin(); it != mLedger.allocations.end(); ++it) { |
| 586 | if (it->channel_id == channel_id && it->is_tx == is_tx) { |
| 587 | mLedger.allocations.erase(it); |
| 588 | break; |
| 589 | } |
| 590 | } |
| 591 | #endif |
| 592 | } |
| 593 | |
| 594 | void RmtMemoryManager::recordRecoveryAllocation(u8 channel_id, size_t words, bool is_tx) FL_NOEXCEPT { |
| 595 | // Check if already exists (shouldn't, but be safe) |
no test coverage detected