aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorKenneth Bell <[email protected]>2021-05-31 17:45:49 -0700
committerRon Evans <[email protected]>2021-06-11 09:07:32 +0200
commit5f9e339cf3cff0d3bdf600cc64fc2245a41a8db1 (patch)
tree7c4ac0656fe32708fd3cd4cedf45d31f15196cc7
parentc017ed224247c1627dcc81dad2d69fb266671678 (diff)
downloadtinygo-5f9e339cf3cff0d3bdf600cc64fc2245a41a8db1.tar.gz
tinygo-5f9e339cf3cff0d3bdf600cc64fc2245a41a8db1.zip
stm32: support pin input interrupts
-rw-r--r--src/examples/pininterrupt/stm32.go10
-rw-r--r--src/machine/board_bluepill.go6
-rw-r--r--src/machine/board_nucleol031k6.go6
-rw-r--r--src/machine/board_nucleol432kc.go6
-rw-r--r--src/machine/board_stm32f4disco.go4
-rw-r--r--src/machine/machine_stm32.go7
-rw-r--r--src/machine/machine_stm32_exti_afio.go27
-rw-r--r--src/machine/machine_stm32_exti_exti.go26
-rw-r--r--src/machine/machine_stm32_exti_syscfg.go27
-rw-r--r--src/machine/machine_stm32_gpio_reva.go92
-rw-r--r--src/machine/machine_stm32_gpio_revb.go79
-rw-r--r--src/machine/machine_stm32f4.go41
-rw-r--r--src/machine/machine_stm32f7.go41
-rw-r--r--src/machine/machine_stm32l0.go42
-rw-r--r--src/machine/machine_stm32l4.go54
-rw-r--r--src/machine/machine_stm32l5.go59
16 files changed, 527 insertions, 0 deletions
diff --git a/src/examples/pininterrupt/stm32.go b/src/examples/pininterrupt/stm32.go
new file mode 100644
index 000000000..30a86313b
--- /dev/null
+++ b/src/examples/pininterrupt/stm32.go
@@ -0,0 +1,10 @@
+// +build stm32
+
+package main
+
+import "machine"
+
+const (
+ buttonMode = machine.PinInputPulldown
+ buttonPinChange = machine.PinRising | machine.PinFalling
+)
diff --git a/src/machine/board_bluepill.go b/src/machine/board_bluepill.go
index 6d0e4dd91..ce925025f 100644
--- a/src/machine/board_bluepill.go
+++ b/src/machine/board_bluepill.go
@@ -11,6 +11,12 @@ const (
LED = PC13
)
+const (
+ // This board does not have a user button, so
+ // use first GPIO pin by default
+ BUTTON = PA0
+)
+
var Serial = UART1
// UART pins
diff --git a/src/machine/board_nucleol031k6.go b/src/machine/board_nucleol031k6.go
index 695dd8b0e..a758ba932 100644
--- a/src/machine/board_nucleol031k6.go
+++ b/src/machine/board_nucleol031k6.go
@@ -14,6 +14,12 @@ const (
)
const (
+ // This board does not have a user button, so
+ // use first GPIO pin by default
+ BUTTON = PA0
+)
+
+const (
// Arduino Pins
A0 = PA0 // ADC_IN0
A1 = PA1 // ADC_IN1
diff --git a/src/machine/board_nucleol432kc.go b/src/machine/board_nucleol432kc.go
index 8f32c46a1..d44e0f4fd 100644
--- a/src/machine/board_nucleol432kc.go
+++ b/src/machine/board_nucleol432kc.go
@@ -14,6 +14,12 @@ const (
)
const (
+ // This board does not have a user button, so
+ // use first GPIO pin by default
+ BUTTON = PA0
+)
+
+const (
// Arduino Pins
A0 = PA0
A1 = PA1
diff --git a/src/machine/board_stm32f4disco.go b/src/machine/board_stm32f4disco.go
index 7a0616079..49f5650fd 100644
--- a/src/machine/board_stm32f4disco.go
+++ b/src/machine/board_stm32f4disco.go
@@ -20,6 +20,10 @@ const (
LED_BLUE = PD15
)
+const (
+ BUTTON = PA0
+)
+
// UART pins
const (
UART_TX_PIN = PA2
diff --git a/src/machine/machine_stm32.go b/src/machine/machine_stm32.go
index 363036ca2..0ba9ef8d6 100644
--- a/src/machine/machine_stm32.go
+++ b/src/machine/machine_stm32.go
@@ -31,6 +31,13 @@ const (
// Also, the stm32f1xx series handles things differently from the stm32f0/2/3/4
// ---------- General pin operations ----------
+type PinChange uint8
+
+const (
+ PinRising PinChange = 1 << iota
+ PinFalling
+ PinToggle = PinRising | PinFalling
+)
// Set the pin to high or low.
// Warning: only use this on an output pin!
diff --git a/src/machine/machine_stm32_exti_afio.go b/src/machine/machine_stm32_exti_afio.go
new file mode 100644
index 000000000..aee4936ac
--- /dev/null
+++ b/src/machine/machine_stm32_exti_afio.go
@@ -0,0 +1,27 @@
+// +build stm32f1
+
+package machine
+
+import (
+ "device/stm32"
+ "runtime/volatile"
+)
+
+func getEXTIConfigRegister(pin uint8) *volatile.Register32 {
+ switch (pin & 0xf) / 4 {
+ case 0:
+ return &stm32.AFIO.EXTICR1
+ case 1:
+ return &stm32.AFIO.EXTICR2
+ case 2:
+ return &stm32.AFIO.EXTICR3
+ case 3:
+ return &stm32.AFIO.EXTICR4
+ }
+ return nil
+}
+
+func enableEXTIConfigRegisters() {
+ // Enable AFIO
+ stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_AFIOEN)
+}
diff --git a/src/machine/machine_stm32_exti_exti.go b/src/machine/machine_stm32_exti_exti.go
new file mode 100644
index 000000000..73db5e1e4
--- /dev/null
+++ b/src/machine/machine_stm32_exti_exti.go
@@ -0,0 +1,26 @@
+// +build stm32l5
+
+package machine
+
+import (
+ "device/stm32"
+ "runtime/volatile"
+)
+
+func getEXTIConfigRegister(pin uint8) *volatile.Register32 {
+ switch (pin & 0xf) / 4 {
+ case 0:
+ return &stm32.EXTI.EXTICR1
+ case 1:
+ return &stm32.EXTI.EXTICR2
+ case 2:
+ return &stm32.EXTI.EXTICR3
+ case 3:
+ return &stm32.EXTI.EXTICR4
+ }
+ return nil
+}
+
+func enableEXTIConfigRegisters() {
+ // No-op
+}
diff --git a/src/machine/machine_stm32_exti_syscfg.go b/src/machine/machine_stm32_exti_syscfg.go
new file mode 100644
index 000000000..34d111fbe
--- /dev/null
+++ b/src/machine/machine_stm32_exti_syscfg.go
@@ -0,0 +1,27 @@
+// +build stm32,!stm32f1,!stm32l5
+
+package machine
+
+import (
+ "device/stm32"
+ "runtime/volatile"
+)
+
+func getEXTIConfigRegister(pin uint8) *volatile.Register32 {
+ switch (pin & 0xf) / 4 {
+ case 0:
+ return &stm32.SYSCFG.EXTICR1
+ case 1:
+ return &stm32.SYSCFG.EXTICR2
+ case 2:
+ return &stm32.SYSCFG.EXTICR3
+ case 3:
+ return &stm32.SYSCFG.EXTICR4
+ }
+ return nil
+}
+
+func enableEXTIConfigRegisters() {
+ // Enable SYSCFG
+ stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SYSCFGEN)
+}
diff --git a/src/machine/machine_stm32_gpio_reva.go b/src/machine/machine_stm32_gpio_reva.go
new file mode 100644
index 000000000..3c0d4fe02
--- /dev/null
+++ b/src/machine/machine_stm32_gpio_reva.go
@@ -0,0 +1,92 @@
+// +build stm32,!stm32l4,!stm32l5
+
+package machine
+
+import (
+ "device/stm32"
+)
+
+// This variant of the GPIO input interrupt logic is for
+// chips with a smaller number of interrupt channels
+// (that fits in a single register).
+
+//
+// STM32 allows one interrupt source per pin number, with
+// the same pin number in different ports sharing a single
+// interrupt source (so PA0, PB0, PC0 all share). Only a
+// single physical pin can be connected to each interrupt
+// line.
+//
+// To call interrupt callbacks, we record here for each
+// pin number the callback and the actual associated pin.
+//
+
+// Callbacks for pin interrupt events
+var pinCallbacks [16]func(Pin)
+
+// The pin currently associated with interrupt callback
+// for a given slot.
+var interruptPins [16]Pin
+
+// SetInterrupt sets an interrupt to be executed when a particular pin changes
+// state. The pin should already be configured as an input, including a pull up
+// or down if no external pull is provided.
+//
+// This call will replace a previously set callback on this pin. You can pass a
+// nil func to unset the pin change interrupt. If you do so, the change
+// parameter is ignored and can be set to any value (such as 0).
+func (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error {
+ port := uint32(uint8(p) / 16)
+ pin := uint8(p) % 16
+
+ enableEXTIConfigRegisters()
+
+ if callback == nil {
+ stm32.EXTI.IMR.ClearBits(1 << pin)
+ pinCallbacks[pin] = nil
+ return nil
+ }
+
+ if pinCallbacks[pin] != nil {
+ // The pin was already configured.
+ // To properly re-configure a pin, unset it first and set a new
+ // configuration.
+ return ErrNoPinChangeChannel
+ }
+
+ // Set the callback now (before the interrupt is enabled) to avoid
+ // possible race condition
+ pinCallbacks[pin] = callback
+ interruptPins[pin] = p
+
+ crReg := getEXTIConfigRegister(pin)
+ shift := (pin & 0x3) * 4
+ crReg.ReplaceBits(port, 0xf, shift)
+
+ if (change & PinRising) != 0 {
+ stm32.EXTI.RTSR.SetBits(1 << pin)
+ }
+ if (change & PinFalling) != 0 {
+ stm32.EXTI.FTSR.SetBits(1 << pin)
+ }
+ stm32.EXTI.IMR.SetBits(1 << pin)
+
+ intr := p.registerInterrupt()
+ intr.SetPriority(0)
+ intr.Enable()
+
+ return nil
+}
+
+func handlePinInterrupt(pin uint8) {
+ if stm32.EXTI.PR.HasBits(1 << pin) {
+ // Writing 1 to the pending register clears the
+ // pending flag for that bit
+ stm32.EXTI.PR.Set(1 << pin)
+
+ callback := pinCallbacks[pin]
+ if callback != nil {
+ callback(interruptPins[pin])
+ }
+ }
+}
diff --git a/src/machine/machine_stm32_gpio_revb.go b/src/machine/machine_stm32_gpio_revb.go
new file mode 100644
index 000000000..1a0e35378
--- /dev/null
+++ b/src/machine/machine_stm32_gpio_revb.go
@@ -0,0 +1,79 @@
+// +build stm32l4 stm32l5
+
+package machine
+
+import (
+ "device/stm32"
+)
+
+// This variant of the GPIO input interrupt logic is for
+// chips with a larger number of interrupt channels (more
+// than fits in a single register).
+
+//
+// STM32 allows one interrupt source per pin number, with
+// the same pin number in different ports sharing a single
+// interrupt source (so PA0, PB0, PC0 all share). Only a
+// single physical pin can be connected to each interrupt
+// line.
+//
+// To call interrupt callbacks, we record here for each
+// pin number the callback and the actual associated pin.
+//
+
+// Callbacks for pin interrupt events
+var pinCallbacks [16]func(Pin)
+
+// The pin currently associated with interrupt callback
+// for a given slot.
+var interruptPins [16]Pin
+
+// SetInterrupt sets an interrupt to be executed when a particular pin changes
+// state. The pin should already be configured as an input, including a pull up
+// or down if no external pull is provided.
+//
+// This call will replace a previously set callback on this pin. You can pass a
+// nil func to unset the pin change interrupt. If you do so, the change
+// parameter is ignored and can be set to any value (such as 0).
+func (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error {
+ port := uint32(uint8(p) / 16)
+ pin := uint8(p) % 16
+
+ enableEXTIConfigRegisters()
+
+ if callback == nil {
+ stm32.EXTI.IMR1.ClearBits(1 << pin)
+ pinCallbacks[pin] = nil
+ return nil
+ }
+
+ if pinCallbacks[pin] != nil {
+ // The pin was already configured.
+ // To properly re-configure a pin, unset it first and set a new
+ // configuration.
+ return ErrNoPinChangeChannel
+ }
+
+ // Set the callback now (before the interrupt is enabled) to avoid
+ // possible race condition
+ pinCallbacks[pin] = callback
+ interruptPins[pin] = p
+
+ crReg := getEXTIConfigRegister(pin)
+ shift := (pin & 0x3) * 4
+ crReg.ReplaceBits(port, 0xf, shift)
+
+ if (change & PinRising) != 0 {
+ stm32.EXTI.RTSR1.SetBits(1 << pin)
+ }
+ if (change & PinFalling) != 0 {
+ stm32.EXTI.FTSR1.SetBits(1 << pin)
+ }
+ stm32.EXTI.IMR1.SetBits(1 << pin)
+
+ intr := p.registerInterrupt()
+ intr.SetPriority(0)
+ intr.Enable()
+
+ return nil
+}
diff --git a/src/machine/machine_stm32f4.go b/src/machine/machine_stm32f4.go
index 3e6156606..652757a3b 100644
--- a/src/machine/machine_stm32f4.go
+++ b/src/machine/machine_stm32f4.go
@@ -200,6 +200,47 @@ func (p Pin) enableClock() {
}
}
+func (p Pin) registerInterrupt() interrupt.Interrupt {
+ pin := uint8(p) % 16
+
+ switch pin {
+ case 0:
+ return interrupt.New(stm32.IRQ_EXTI0, func(interrupt.Interrupt) { handlePinInterrupt(0) })
+ case 1:
+ return interrupt.New(stm32.IRQ_EXTI1, func(interrupt.Interrupt) { handlePinInterrupt(1) })
+ case 2:
+ return interrupt.New(stm32.IRQ_EXTI2, func(interrupt.Interrupt) { handlePinInterrupt(2) })
+ case 3:
+ return interrupt.New(stm32.IRQ_EXTI3, func(interrupt.Interrupt) { handlePinInterrupt(3) })
+ case 4:
+ return interrupt.New(stm32.IRQ_EXTI4, func(interrupt.Interrupt) { handlePinInterrupt(4) })
+ case 5:
+ return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(5) })
+ case 6:
+ return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(6) })
+ case 7:
+ return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(7) })
+ case 8:
+ return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(8) })
+ case 9:
+ return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(9) })
+ case 10:
+ return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(10) })
+ case 11:
+ return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(11) })
+ case 12:
+ return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(12) })
+ case 13:
+ return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(13) })
+ case 14:
+ return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(14) })
+ case 15:
+ return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(15) })
+ }
+
+ return interrupt.Interrupt{}
+}
+
// Enable peripheral clock
func enableAltFuncClock(bus unsafe.Pointer) {
switch bus {
diff --git a/src/machine/machine_stm32f7.go b/src/machine/machine_stm32f7.go
index 51235709e..76f1007ac 100644
--- a/src/machine/machine_stm32f7.go
+++ b/src/machine/machine_stm32f7.go
@@ -309,6 +309,47 @@ func enableAltFuncClock(bus unsafe.Pointer) {
}
}
+func (p Pin) registerInterrupt() interrupt.Interrupt {
+ pin := uint8(p) % 16
+
+ switch pin {
+ case 0:
+ return interrupt.New(stm32.IRQ_EXTI0, func(interrupt.Interrupt) { handlePinInterrupt(0) })
+ case 1:
+ return interrupt.New(stm32.IRQ_EXTI1, func(interrupt.Interrupt) { handlePinInterrupt(1) })
+ case 2:
+ return interrupt.New(stm32.IRQ_EXTI2, func(interrupt.Interrupt) { handlePinInterrupt(2) })
+ case 3:
+ return interrupt.New(stm32.IRQ_EXTI3, func(interrupt.Interrupt) { handlePinInterrupt(3) })
+ case 4:
+ return interrupt.New(stm32.IRQ_EXTI4, func(interrupt.Interrupt) { handlePinInterrupt(4) })
+ case 5:
+ return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(5) })
+ case 6:
+ return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(6) })
+ case 7:
+ return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(7) })
+ case 8:
+ return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(8) })
+ case 9:
+ return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(9) })
+ case 10:
+ return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(10) })
+ case 11:
+ return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(11) })
+ case 12:
+ return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(12) })
+ case 13:
+ return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(13) })
+ case 14:
+ return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(14) })
+ case 15:
+ return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(15) })
+ }
+
+ return interrupt.Interrupt{}
+}
+
//---------- Timer related code
var (
diff --git a/src/machine/machine_stm32l0.go b/src/machine/machine_stm32l0.go
index a25d6c9f2..f2a95e8d3 100644
--- a/src/machine/machine_stm32l0.go
+++ b/src/machine/machine_stm32l0.go
@@ -6,6 +6,7 @@ package machine
import (
"device/stm32"
+ "runtime/interrupt"
)
func CPUFrequency() uint32 {
@@ -147,6 +148,47 @@ func (p Pin) enableClock() {
}
}
+func (p Pin) registerInterrupt() interrupt.Interrupt {
+ pin := uint8(p) % 16
+
+ switch pin {
+ case 0:
+ return interrupt.New(stm32.IRQ_EXTI0_1, func(interrupt.Interrupt) { handlePinInterrupt(0) })
+ case 1:
+ return interrupt.New(stm32.IRQ_EXTI0_1, func(interrupt.Interrupt) { handlePinInterrupt(1) })
+ case 2:
+ return interrupt.New(stm32.IRQ_EXTI2_3, func(interrupt.Interrupt) { handlePinInterrupt(2) })
+ case 3:
+ return interrupt.New(stm32.IRQ_EXTI2_3, func(interrupt.Interrupt) { handlePinInterrupt(3) })
+ case 4:
+ return interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(4) })
+ case 5:
+ return interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(5) })
+ case 6:
+ return interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(6) })
+ case 7:
+ return interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(7) })
+ case 8:
+ return interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(8) })
+ case 9:
+ return interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(9) })
+ case 10:
+ return interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(10) })
+ case 11:
+ return interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(11) })
+ case 12:
+ return interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(12) })
+ case 13:
+ return interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(13) })
+ case 14:
+ return interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(14) })
+ case 15:
+ return interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(15) })
+ }
+
+ return interrupt.Interrupt{}
+}
+
//---------- UART related types and code
// Configure the UART.
diff --git a/src/machine/machine_stm32l4.go b/src/machine/machine_stm32l4.go
index c464fa702..be58e9b5f 100644
--- a/src/machine/machine_stm32l4.go
+++ b/src/machine/machine_stm32l4.go
@@ -203,6 +203,60 @@ func enableAltFuncClock(bus unsafe.Pointer) {
}
}
+func handlePinInterrupt(pin uint8) {
+ if stm32.EXTI.PR1.HasBits(1 << pin) {
+ // Writing 1 to the pending register clears the
+ // pending flag for that bit
+ stm32.EXTI.PR1.Set(1 << pin)
+
+ callback := pinCallbacks[pin]
+ if callback != nil {
+ callback(interruptPins[pin])
+ }
+ }
+}
+
+func (p Pin) registerInterrupt() interrupt.Interrupt {
+ pin := uint8(p) % 16
+
+ switch pin {
+ case 0:
+ return interrupt.New(stm32.IRQ_EXTI0, func(interrupt.Interrupt) { handlePinInterrupt(0) })
+ case 1:
+ return interrupt.New(stm32.IRQ_EXTI1, func(interrupt.Interrupt) { handlePinInterrupt(1) })
+ case 2:
+ return interrupt.New(stm32.IRQ_EXTI2, func(interrupt.Interrupt) { handlePinInterrupt(2) })
+ case 3:
+ return interrupt.New(stm32.IRQ_EXTI3, func(interrupt.Interrupt) { handlePinInterrupt(3) })
+ case 4:
+ return interrupt.New(stm32.IRQ_EXTI4, func(interrupt.Interrupt) { handlePinInterrupt(4) })
+ case 5:
+ return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(5) })
+ case 6:
+ return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(6) })
+ case 7:
+ return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(7) })
+ case 8:
+ return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(8) })
+ case 9:
+ return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(9) })
+ case 10:
+ return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(10) })
+ case 11:
+ return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(11) })
+ case 12:
+ return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(12) })
+ case 13:
+ return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(13) })
+ case 14:
+ return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(14) })
+ case 15:
+ return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(15) })
+ }
+
+ return interrupt.Interrupt{}
+}
+
//---------- SPI related types and code
// SPI on the STM32Fxxx using MODER / alternate function pins
diff --git a/src/machine/machine_stm32l5.go b/src/machine/machine_stm32l5.go
index 23aba7a07..3f2935cc2 100644
--- a/src/machine/machine_stm32l5.go
+++ b/src/machine/machine_stm32l5.go
@@ -271,6 +271,65 @@ func enableAltFuncClock(bus unsafe.Pointer) {
}
}
+func (p Pin) registerInterrupt() interrupt.Interrupt {
+ pin := uint8(p) % 16
+
+ switch pin {
+ case 0:
+ return interrupt.New(stm32.IRQ_EXTI0, func(interrupt.Interrupt) { handlePinInterrupt(0) })
+ case 1:
+ return interrupt.New(stm32.IRQ_EXTI1, func(interrupt.Interrupt) { handlePinInterrupt(1) })
+ case 2:
+ return interrupt.New(stm32.IRQ_EXTI2, func(interrupt.Interrupt) { handlePinInterrupt(2) })
+ case 3:
+ return interrupt.New(stm32.IRQ_EXTI3, func(interrupt.Interrupt) { handlePinInterrupt(3) })
+ case 4:
+ return interrupt.New(stm32.IRQ_EXTI4, func(interrupt.Interrupt) { handlePinInterrupt(4) })
+ case 5:
+ return interrupt.New(stm32.IRQ_EXTI5, func(interrupt.Interrupt) { handlePinInterrupt(5) })
+ case 6:
+ return interrupt.New(stm32.IRQ_EXTI6, func(interrupt.Interrupt) { handlePinInterrupt(6) })
+ case 7:
+ return interrupt.New(stm32.IRQ_EXTI7, func(interrupt.Interrupt) { handlePinInterrupt(7) })
+ case 8:
+ return interrupt.New(stm32.IRQ_EXTI8, func(interrupt.Interrupt) { handlePinInterrupt(8) })
+ case 9:
+ return interrupt.New(stm32.IRQ_EXTI9, func(interrupt.Interrupt) { handlePinInterrupt(9) })
+ case 10:
+ return interrupt.New(stm32.IRQ_EXTI10, func(interrupt.Interrupt) { handlePinInterrupt(10) })
+ case 11:
+ return interrupt.New(stm32.IRQ_EXTI11, func(interrupt.Interrupt) { handlePinInterrupt(11) })
+ case 12:
+ return interrupt.New(stm32.IRQ_EXTI12, func(interrupt.Interrupt) { handlePinInterrupt(12) })
+ case 13:
+ return interrupt.New(stm32.IRQ_EXTI13, func(interrupt.Interrupt) { handlePinInterrupt(13) })
+ case 14:
+ return interrupt.New(stm32.IRQ_EXTI14, func(interrupt.Interrupt) { handlePinInterrupt(14) })
+ case 15:
+ return interrupt.New(stm32.IRQ_EXTI15, func(interrupt.Interrupt) { handlePinInterrupt(15) })
+ }
+
+ return interrupt.Interrupt{}
+}
+
+func handlePinInterrupt(pin uint8) {
+ // The pin abstraction doesn't differentiate pull-up
+ // events from pull-down events, so combine them to
+ // a single call here.
+
+ if stm32.EXTI.RPR1.HasBits(1<<pin) || stm32.EXTI.FPR1.HasBits(1<<pin) {
+ // Writing 1 to the pending register clears the
+ // pending flag for that bit
+ stm32.EXTI.RPR1.Set(1 << pin)
+ stm32.EXTI.FPR1.Set(1 << pin)
+
+ callback := pinCallbacks[pin]
+ if callback != nil {
+ callback(interruptPins[pin])
+ }
+ }
+}
+
//---------- Timer related code
var (