164 строки
5 КиБ
Go
164 строки
5 КиБ
Go
//go:build stm32 && !stm32f103
|
|
|
|
package machine
|
|
|
|
import (
|
|
"device/stm32"
|
|
)
|
|
|
|
// GPIO for the stm32 families except the stm32f1xx which uses a simpler but
|
|
// less flexible mechanism. Extend the go:build directive above to exclude other
|
|
// models in the stm32f1xx series as necessary
|
|
|
|
const (
|
|
// Mode Flag
|
|
PinOutput PinMode = 0
|
|
PinInput PinMode = PinInputFloating
|
|
PinInputFloating PinMode = 1
|
|
PinInputPulldown PinMode = 2
|
|
PinInputPullup PinMode = 3
|
|
|
|
// for UART
|
|
PinModeUARTTX PinMode = 4
|
|
PinModeUARTRX PinMode = 5
|
|
|
|
// for I2C
|
|
PinModeI2CSCL PinMode = 6
|
|
PinModeI2CSDA PinMode = 7
|
|
|
|
// for SPI
|
|
PinModeSPICLK PinMode = 8
|
|
PinModeSPISDO PinMode = 9
|
|
PinModeSPISDI PinMode = 10
|
|
|
|
// for analog/ADC
|
|
PinInputAnalog PinMode = 11
|
|
|
|
// for PWM
|
|
PinModePWMOutput PinMode = 12
|
|
)
|
|
|
|
// Define several bitfields that have different names across chip families but
|
|
// essentially have the same meaning.
|
|
const (
|
|
// MODER bitfields.
|
|
gpioModeInput = 0
|
|
gpioModeOutput = 1
|
|
gpioModeAlternate = 2
|
|
gpioModeAnalog = 3
|
|
gpioModeMask = 0x3
|
|
|
|
// PUPDR bitfields.
|
|
gpioPullFloating = 0
|
|
gpioPullUp = 1
|
|
gpioPullDown = 2
|
|
gpioPullMask = 0x3
|
|
|
|
// OSPEED bitfields.
|
|
gpioOutputSpeedVeryHigh = 3
|
|
gpioOutputSpeedHigh = 2
|
|
gpioOutputSpeedMedium = 1
|
|
gpioOutputSpeedLow = 0
|
|
gpioOutputSpeedMask = 0x3
|
|
)
|
|
|
|
// Configure this pin with the given configuration
|
|
func (p Pin) Configure(config PinConfig) {
|
|
// Use the default system alternate function; this
|
|
// will only be used if you try to call this with
|
|
// one of the peripheral modes instead of vanilla GPIO.
|
|
p.ConfigureAltFunc(config, 0)
|
|
}
|
|
|
|
// Configure this pin with the given configuration including alternate
|
|
//
|
|
// function mapping if necessary.
|
|
func (p Pin) ConfigureAltFunc(config PinConfig, altFunc uint8) {
|
|
// Configure the GPIO pin.
|
|
p.enableClock()
|
|
port := p.getPort()
|
|
pos := (uint8(p) % 16) * 2 // assume each field is two bits in size (with mask 0x3)
|
|
|
|
switch config.Mode {
|
|
|
|
// GPIO
|
|
case PinInputFloating:
|
|
port.MODER.ReplaceBits(gpioModeInput, gpioModeMask, pos)
|
|
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
|
|
case PinInputPulldown:
|
|
port.MODER.ReplaceBits(gpioModeInput, gpioModeMask, pos)
|
|
port.PUPDR.ReplaceBits(gpioPullDown, gpioPullMask, pos)
|
|
case PinInputPullup:
|
|
port.MODER.ReplaceBits(gpioModeInput, gpioModeMask, pos)
|
|
port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos)
|
|
case PinOutput:
|
|
port.MODER.ReplaceBits(gpioModeOutput, gpioModeMask, pos)
|
|
port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)
|
|
|
|
// UART
|
|
case PinModeUARTTX:
|
|
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
|
|
port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)
|
|
port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos)
|
|
p.SetAltFunc(altFunc)
|
|
case PinModeUARTRX:
|
|
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
|
|
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
|
|
p.SetAltFunc(altFunc)
|
|
|
|
// I2C
|
|
case PinModeI2CSCL:
|
|
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
|
|
port.OTYPER.ReplaceBits(stm32.GPIO_OTYPER_OT0_OpenDrain, stm32.GPIO_OTYPER_OT0_Msk, pos/2)
|
|
port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)
|
|
port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos)
|
|
p.SetAltFunc(altFunc)
|
|
case PinModeI2CSDA:
|
|
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
|
|
port.OTYPER.ReplaceBits(stm32.GPIO_OTYPER_OT0_OpenDrain, stm32.GPIO_OTYPER_OT0_Msk, pos/2)
|
|
port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)
|
|
port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos)
|
|
p.SetAltFunc(altFunc)
|
|
|
|
// SPI
|
|
case PinModeSPICLK:
|
|
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
|
|
port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)
|
|
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
|
|
p.SetAltFunc(altFunc)
|
|
case PinModeSPISDO:
|
|
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
|
|
port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)
|
|
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
|
|
p.SetAltFunc(altFunc)
|
|
case PinModeSPISDI:
|
|
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
|
|
port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)
|
|
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
|
|
p.SetAltFunc(altFunc)
|
|
|
|
// PWM
|
|
case PinModePWMOutput:
|
|
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
|
|
port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)
|
|
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
|
|
p.SetAltFunc(altFunc)
|
|
|
|
// ADC
|
|
case PinInputAnalog:
|
|
port.MODER.ReplaceBits(gpioModeAnalog, gpioModeMask, pos)
|
|
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
|
|
}
|
|
}
|
|
|
|
// SetAltFunc maps the given alternative function to the I/O pin
|
|
func (p Pin) SetAltFunc(af uint8) {
|
|
port := p.getPort()
|
|
pin := uint8(p) % 16
|
|
pos := (pin % 8) * 4
|
|
if pin < 8 {
|
|
port.AFRL.ReplaceBits(uint32(af), 0xf, pos)
|
|
} else {
|
|
port.AFRH.ReplaceBits(uint32(af), 0xf, pos)
|
|
}
|
|
}
|