| 503 | } |
| 504 | |
| 505 | void SPIDualSAMD51::cleanup() { |
| 506 | if (mInitialized) { |
| 507 | // Wait for any pending transmission |
| 508 | if (mTransactionActive) { |
| 509 | waitComplete(); |
| 510 | } |
| 511 | |
| 512 | // Release DMA buffer |
| 513 | mDMABuffer.reset(); |
| 514 | mBufferAcquired = false; |
| 515 | |
| 516 | // Release DMA resources (legacy, for future DMA implementation) |
| 517 | // Note: DMA is not currently implemented (mDmaChannel is always -1) |
| 518 | // These steps are placeholders for when async DMA is added: |
| 519 | // 1. Disable DMA channel via DMAC registers |
| 520 | // 2. Free DMA descriptor memory if dynamically allocated |
| 521 | // 3. Release channel ID back to allocator |
| 522 | if (mDmaChannel != -1) { |
| 523 | // Future DMA cleanup would go here |
| 524 | mDmaChannel = -1; |
| 525 | mDmaDescriptor = nullptr; |
| 526 | } |
| 527 | |
| 528 | if (mSercom != nullptr) { |
| 529 | // Disable SERCOM |
| 530 | mSercom->SPI.CTRLA.bit.ENABLE = 0; |
| 531 | while (mSercom->SPI.SYNCBUSY.bit.ENABLE); |
| 532 | |
| 533 | // Reset SERCOM |
| 534 | mSercom->SPI.CTRLA.bit.SWRST = 1; |
| 535 | while (mSercom->SPI.CTRLA.bit.SWRST || mSercom->SPI.SYNCBUSY.bit.SWRST); |
| 536 | |
| 537 | // Note: We don't disable peripheral clocks as other code may use them |
| 538 | mSercom = nullptr; |
| 539 | } |
| 540 | |
| 541 | mInitialized = false; |
| 542 | } |
| 543 | } |
| 544 | |
| 545 | // ============================================================================ |
| 546 | // Factory Implementation |