//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) } }