github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/machine/machine_stm32_moder_gpio.go (about)

     1  //go:build stm32 && !stm32f103
     2  
     3  package machine
     4  
     5  import (
     6  	"device/stm32"
     7  )
     8  
     9  // GPIO for the stm32 families except the stm32f1xx which uses a simpler but
    10  //  less flexible mechanism. Extend the go:build directive above to exclude other
    11  //  models in the stm32f1xx series as necessary
    12  
    13  const (
    14  	// Mode Flag
    15  	PinOutput        PinMode = 0
    16  	PinInput         PinMode = PinInputFloating
    17  	PinInputFloating PinMode = 1
    18  	PinInputPulldown PinMode = 2
    19  	PinInputPullup   PinMode = 3
    20  
    21  	// for UART
    22  	PinModeUARTTX PinMode = 4
    23  	PinModeUARTRX PinMode = 5
    24  
    25  	// for I2C
    26  	PinModeI2CSCL PinMode = 6
    27  	PinModeI2CSDA PinMode = 7
    28  
    29  	// for SPI
    30  	PinModeSPICLK PinMode = 8
    31  	PinModeSPISDO PinMode = 9
    32  	PinModeSPISDI PinMode = 10
    33  
    34  	// for analog/ADC
    35  	PinInputAnalog PinMode = 11
    36  
    37  	// for PWM
    38  	PinModePWMOutput PinMode = 12
    39  )
    40  
    41  // Define several bitfields that have different names across chip families but
    42  // essentially have the same meaning.
    43  const (
    44  	// MODER bitfields.
    45  	gpioModeInput     = 0
    46  	gpioModeOutput    = 1
    47  	gpioModeAlternate = 2
    48  	gpioModeAnalog    = 3
    49  	gpioModeMask      = 0x3
    50  
    51  	// PUPDR bitfields.
    52  	gpioPullFloating = 0
    53  	gpioPullUp       = 1
    54  	gpioPullDown     = 2
    55  	gpioPullMask     = 0x3
    56  
    57  	// OSPEED bitfields.
    58  	gpioOutputSpeedVeryHigh = 3
    59  	gpioOutputSpeedHigh     = 2
    60  	gpioOutputSpeedMedium   = 1
    61  	gpioOutputSpeedLow      = 0
    62  	gpioOutputSpeedMask     = 0x3
    63  )
    64  
    65  // Configure this pin with the given configuration
    66  func (p Pin) Configure(config PinConfig) {
    67  	// Use the default system alternate function; this
    68  	//  will only be used if you try to call this with
    69  	//  one of the peripheral modes instead of vanilla GPIO.
    70  	p.ConfigureAltFunc(config, 0)
    71  }
    72  
    73  // Configure this pin with the given configuration including alternate
    74  //
    75  //	function mapping if necessary.
    76  func (p Pin) ConfigureAltFunc(config PinConfig, altFunc uint8) {
    77  	// Configure the GPIO pin.
    78  	p.enableClock()
    79  	port := p.getPort()
    80  	pos := (uint8(p) % 16) * 2 // assume each field is two bits in size (with mask 0x3)
    81  
    82  	switch config.Mode {
    83  
    84  	// GPIO
    85  	case PinInputFloating:
    86  		port.MODER.ReplaceBits(gpioModeInput, gpioModeMask, pos)
    87  		port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
    88  	case PinInputPulldown:
    89  		port.MODER.ReplaceBits(gpioModeInput, gpioModeMask, pos)
    90  		port.PUPDR.ReplaceBits(gpioPullDown, gpioPullMask, pos)
    91  	case PinInputPullup:
    92  		port.MODER.ReplaceBits(gpioModeInput, gpioModeMask, pos)
    93  		port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos)
    94  	case PinOutput:
    95  		port.MODER.ReplaceBits(gpioModeOutput, gpioModeMask, pos)
    96  		port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)
    97  
    98  	// UART
    99  	case PinModeUARTTX:
   100  		port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
   101  		port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)
   102  		port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos)
   103  		p.SetAltFunc(altFunc)
   104  	case PinModeUARTRX:
   105  		port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
   106  		port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
   107  		p.SetAltFunc(altFunc)
   108  
   109  	// I2C
   110  	case PinModeI2CSCL:
   111  		port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
   112  		port.OTYPER.ReplaceBits(stm32.GPIO_OTYPER_OT0_OpenDrain, stm32.GPIO_OTYPER_OT0_Msk, pos/2)
   113  		port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)
   114  		port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos)
   115  		p.SetAltFunc(altFunc)
   116  	case PinModeI2CSDA:
   117  		port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
   118  		port.OTYPER.ReplaceBits(stm32.GPIO_OTYPER_OT0_OpenDrain, stm32.GPIO_OTYPER_OT0_Msk, pos/2)
   119  		port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)
   120  		port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos)
   121  		p.SetAltFunc(altFunc)
   122  
   123  	// SPI
   124  	case PinModeSPICLK:
   125  		port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
   126  		port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)
   127  		port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
   128  		p.SetAltFunc(altFunc)
   129  	case PinModeSPISDO:
   130  		port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
   131  		port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)
   132  		port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
   133  		p.SetAltFunc(altFunc)
   134  	case PinModeSPISDI:
   135  		port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
   136  		port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)
   137  		port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
   138  		p.SetAltFunc(altFunc)
   139  
   140  	// PWM
   141  	case PinModePWMOutput:
   142  		port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
   143  		port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)
   144  		port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
   145  		p.SetAltFunc(altFunc)
   146  
   147  	// ADC
   148  	case PinInputAnalog:
   149  		port.MODER.ReplaceBits(gpioModeAnalog, gpioModeMask, pos)
   150  		port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
   151  	}
   152  }
   153  
   154  // SetAltFunc maps the given alternative function to the I/O pin
   155  func (p Pin) SetAltFunc(af uint8) {
   156  	port := p.getPort()
   157  	pin := uint8(p) % 16
   158  	pos := (pin % 8) * 4
   159  	if pin < 8 {
   160  		port.AFRL.ReplaceBits(uint32(af), 0xf, pos)
   161  	} else {
   162  		port.AFRH.ReplaceBits(uint32(af), 0xf, pos)
   163  	}
   164  }