Skip to content

dma_irqn_acknowledge_channel incorrectly clears ALL channel interrupts #974

@NomiChirps

Description

@NomiChirps

After spending a couple of days chasing this down, I've discovered that attempting to use hw_set_bits (or hw_clear_bits, or hw_xor_bits) with the DMA INTS0/INTS1 interrupt flag register causes ALL of the active channel interrupts to be cleared, not just the ones in the bitmask. This happens even when an empty bitmask is used.

The correct behavior is obtained by simply assigning a bitmask to the register, e.g. dma_hw->ints0 = 1 << channel_num. Unfortunately the current implementation of dma_irqn_acknowledge_channel uses hw_set_bits.

Discussion: https://forums.raspberrypi.com/viewtopic.php?p=2029939
Minimal reproduction: https://github.com/NomiChirps/missed_interrupt

The DMA INTS0/INTS1 register is marked as "WC" type in the RP2040 datasheet:

WC
This is a single bit that is typically set by a piece of hardware and then written to by the processor to clear the bit. The
bit is cleared by writing a 1, using either a normal write or the clear alias. See Section 2.1.2 for more information about
the clear alias.

So it's advertised that hw_clear_bits() should work with this register, and not clear that hw_set_bits() does anything well-defined. My testing has found that none of the hw_*_bits() aliases function as advertised here, though; they all clear the entire register no matter what bitmask is used.

In conclusion...

  • I'd be happy to author a pull request to correct dma_irqn_acknowledge_channel, if you'd like.
  • I think it might be worth checking to make sure no other "WC"-typed registers are accidentally misused(?) this way by the SDK.
  • It's a mystery why hw_clear_bits() doesn't work with this register, although the data sheet seems to advertise that it should.

Thanks for reading :)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions