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 }