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

     1  //go:build stm32
     2  
     3  package machine
     4  
     5  import (
     6  	"device/stm32"
     7  
     8  	"runtime/volatile"
     9  	"unsafe"
    10  )
    11  
    12  const deviceName = stm32.Device
    13  
    14  // Peripheral abstraction layer for the stm32.
    15  
    16  const (
    17  	portA Pin = iota * 16
    18  	portB
    19  	portC
    20  	portD
    21  	portE
    22  	portF
    23  	portG
    24  	portH
    25  	portI
    26  	portJ
    27  	portK
    28  )
    29  
    30  // Peripheral operations sequence:
    31  //  1. Enable the clock to the alternate function.
    32  //  2. Enable clock to corresponding GPIO
    33  //  3. Attach the alternate function.
    34  //  4. Configure the input-output port and pins (of the corresponding GPIOx) to match the AF .
    35  //  5. If desired enable the nested vector interrupt control to generate interrupts.
    36  //  6. Program the AF/peripheral for the required configuration (eg baud rate for a USART) .
    37  
    38  // Given that the stm32 family has the AF and GPIO on different registers based on the chip,
    39  //  use the main function here for configuring, and use hooks in the more specific chip
    40  //  definition files
    41  // Also, the stm32f1xx series handles things differently from the stm32f0/2/3/4
    42  
    43  // ---------- General pin operations ----------
    44  type PinChange uint8
    45  
    46  const (
    47  	PinRising PinChange = 1 << iota
    48  	PinFalling
    49  	PinToggle = PinRising | PinFalling
    50  )
    51  
    52  // Set the pin to high or low.
    53  // Warning: only use this on an output pin!
    54  func (p Pin) Set(high bool) {
    55  	port := p.getPort()
    56  	pin := uint8(p) % 16
    57  	if high {
    58  		port.BSRR.Set(1 << pin)
    59  	} else {
    60  		port.BSRR.Set(1 << (pin + 16))
    61  	}
    62  }
    63  
    64  // Get returns the current value of a GPIO pin when the pin is configured as an
    65  // input or as an output.
    66  func (p Pin) Get() bool {
    67  	port := p.getPort()
    68  	pin := uint8(p) % 16
    69  	val := port.IDR.Get() & (1 << pin)
    70  	return (val > 0)
    71  }
    72  
    73  // PortMaskSet returns the register and mask to enable a given GPIO pin. This
    74  // can be used to implement bit-banged drivers.
    75  func (p Pin) PortMaskSet() (*uint32, uint32) {
    76  	port := p.getPort()
    77  	pin := uint8(p) % 16
    78  	return &port.BSRR.Reg, 1 << pin
    79  }
    80  
    81  // PortMaskClear returns the register and mask to disable a given port. This can
    82  // be used to implement bit-banged drivers.
    83  func (p Pin) PortMaskClear() (*uint32, uint32) {
    84  	port := p.getPort()
    85  	pin := uint8(p) % 16
    86  	return &port.BSRR.Reg, 1 << (pin + 16)
    87  }
    88  
    89  var deviceID [12]byte
    90  
    91  // DeviceID returns an identifier that is unique within
    92  // a particular chipset.
    93  //
    94  // The identity is one burnt into the MCU itself.
    95  //
    96  // The length of the device ID for STM32 is 12 bytes (96 bits).
    97  func DeviceID() []byte {
    98  	for i := 0; i < len(deviceID); i++ {
    99  		word := (*volatile.Register32)(unsafe.Pointer(deviceIDAddr[i/4])).Get()
   100  		deviceID[i] = byte(word >> ((i % 4) * 8))
   101  	}
   102  
   103  	return deviceID[:]
   104  }