diff options
author | Kenneth Bell <[email protected]> | 2021-05-31 17:45:49 -0700 |
---|---|---|
committer | Ron Evans <[email protected]> | 2021-06-11 09:07:32 +0200 |
commit | 5f9e339cf3cff0d3bdf600cc64fc2245a41a8db1 (patch) | |
tree | 7c4ac0656fe32708fd3cd4cedf45d31f15196cc7 | |
parent | c017ed224247c1627dcc81dad2d69fb266671678 (diff) | |
download | tinygo-5f9e339cf3cff0d3bdf600cc64fc2245a41a8db1.tar.gz tinygo-5f9e339cf3cff0d3bdf600cc64fc2245a41a8db1.zip |
stm32: support pin input interrupts
-rw-r--r-- | src/examples/pininterrupt/stm32.go | 10 | ||||
-rw-r--r-- | src/machine/board_bluepill.go | 6 | ||||
-rw-r--r-- | src/machine/board_nucleol031k6.go | 6 | ||||
-rw-r--r-- | src/machine/board_nucleol432kc.go | 6 | ||||
-rw-r--r-- | src/machine/board_stm32f4disco.go | 4 | ||||
-rw-r--r-- | src/machine/machine_stm32.go | 7 | ||||
-rw-r--r-- | src/machine/machine_stm32_exti_afio.go | 27 | ||||
-rw-r--r-- | src/machine/machine_stm32_exti_exti.go | 26 | ||||
-rw-r--r-- | src/machine/machine_stm32_exti_syscfg.go | 27 | ||||
-rw-r--r-- | src/machine/machine_stm32_gpio_reva.go | 92 | ||||
-rw-r--r-- | src/machine/machine_stm32_gpio_revb.go | 79 | ||||
-rw-r--r-- | src/machine/machine_stm32f4.go | 41 | ||||
-rw-r--r-- | src/machine/machine_stm32f7.go | 41 | ||||
-rw-r--r-- | src/machine/machine_stm32l0.go | 42 | ||||
-rw-r--r-- | src/machine/machine_stm32l4.go | 54 | ||||
-rw-r--r-- | src/machine/machine_stm32l5.go | 59 |
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 ( |