github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/machine/machine_rp2040_sync.go (about)

     1  //go:build rp2040
     2  
     3  package machine
     4  
     5  import (
     6  	"device/rp"
     7  )
     8  
     9  // machine_rp2040_sync.go contains interrupt and
    10  // lock primitives similar to those found in Pico SDK's
    11  // irq.c
    12  
    13  const (
    14  	// Number of spin locks available
    15  	_NUMSPINLOCKS = 32
    16  	// Number of interrupt handlers available
    17  	_NUMIRQ               = 32
    18  	_PICO_SPINLOCK_ID_IRQ = 9
    19  	_NUMBANK0_GPIOS       = 30
    20  )
    21  
    22  // Clears interrupt flag on a pin
    23  func (p Pin) acknowledgeInterrupt(change PinChange) {
    24  	ioBank0.intR[p>>3].Set(p.ioIntBit(change))
    25  }
    26  
    27  // Basic interrupt setting via ioBANK0 for GPIO interrupts.
    28  func (p Pin) setInterrupt(change PinChange, enabled bool) {
    29  	// Separate mask/force/status per-core, so check which core called, and
    30  	// set the relevant IRQ controls.
    31  	switch CurrentCore() {
    32  	case 0:
    33  		p.ctrlSetInterrupt(change, enabled, &ioBank0.proc0IRQctrl)
    34  	case 1:
    35  		p.ctrlSetInterrupt(change, enabled, &ioBank0.proc1IRQctrl)
    36  	}
    37  }
    38  
    39  // ctrlSetInterrupt acknowledges any pending interrupt and enables or disables
    40  // the interrupt for a given IRQ control bank (IOBANK, DormantIRQ, QSPI).
    41  //
    42  // pico-sdk calls this the _gpio_set_irq_enabled, not to be confused with
    43  // gpio_set_irq_enabled (no leading underscore).
    44  func (p Pin) ctrlSetInterrupt(change PinChange, enabled bool, base *irqCtrl) {
    45  	p.acknowledgeInterrupt(change)
    46  	enReg := &base.intE[p>>3]
    47  	if enabled {
    48  		enReg.SetBits(p.ioIntBit(change))
    49  	} else {
    50  		enReg.ClearBits(p.ioIntBit(change))
    51  	}
    52  }
    53  
    54  // Enable or disable a specific interrupt on the executing core.
    55  // num is the interrupt number which must be in [0,31].
    56  func irqSet(num uint32, enabled bool) {
    57  	if num >= _NUMIRQ {
    58  		return
    59  	}
    60  	irqSetMask(1<<num, enabled)
    61  }
    62  
    63  func irqSetMask(mask uint32, enabled bool) {
    64  	if enabled {
    65  		// Clear pending before enable
    66  		// (if IRQ is actually asserted, it will immediately re-pend)
    67  		rp.PPB.NVIC_ICPR.Set(mask)
    68  		rp.PPB.NVIC_ISER.Set(mask)
    69  	} else {
    70  		rp.PPB.NVIC_ICER.Set(mask)
    71  	}
    72  }