github.com/aykevl/tinygo@v0.5.0/src/machine/machine_stm32f407.go (about)

     1  // +build stm32,stm32f407
     2  
     3  package machine
     4  
     5  // Peripheral abstraction layer for the stm32.
     6  
     7  import (
     8  	"device/arm"
     9  	"device/stm32"
    10  )
    11  
    12  const CPU_FREQUENCY = 168000000
    13  
    14  const (
    15  	// Mode Flag
    16  	GPIO_OUTPUT         = 0
    17  	GPIO_INPUT          = GPIO_INPUT_PULLDOWN
    18  	GPIO_INPUT_FLOATING = 1
    19  	GPIO_INPUT_PULLDOWN = 2
    20  	GPIO_INPUT_PULLUP   = 3
    21  
    22  	// for UART
    23  	GPIO_UART_TX = 4
    24  	GPIO_UART_RX = 5
    25  
    26  	//GPIOx_MODER
    27  	GPIO_MODE_INPUT          = 0
    28  	GPIO_MODE_GENERAL_OUTPUT = 1
    29  	GPIO_MODE_ALTERNABTIVE   = 2
    30  	GPIO_MODE_ANALOG         = 3
    31  
    32  	//GPIOx_OTYPER
    33  	GPIO_OUTPUT_MODE_PUSH_PULL  = 0
    34  	GPIO_OUTPUT_MODE_OPEN_DRAIN = 1
    35  
    36  	// GPIOx_OSPEEDR
    37  	GPIO_SPEED_LOW     = 0
    38  	GPIO_SPEED_MID     = 1
    39  	GPIO_SPEED_HI      = 2
    40  	GPIO_SPEED_VERY_HI = 3
    41  
    42  	// GPIOx_PUPDR
    43  	GPIO_FLOATING  = 0
    44  	GPIO_PULL_UP   = 1
    45  	GPIO_PULL_DOWN = 2
    46  )
    47  
    48  func (p GPIO) getPort() *stm32.GPIO_Type {
    49  	switch p.Pin / 16 {
    50  	case 0:
    51  		return stm32.GPIOA
    52  	case 1:
    53  		return stm32.GPIOB
    54  	case 2:
    55  		return stm32.GPIOC
    56  	case 3:
    57  		return stm32.GPIOD
    58  	case 4:
    59  		return stm32.GPIOE
    60  	case 5:
    61  		return stm32.GPIOF
    62  	case 6:
    63  		return stm32.GPIOG
    64  	case 7:
    65  		return stm32.GPIOH
    66  	case 8:
    67  		return stm32.GPIOI
    68  	default:
    69  		panic("machine: unknown port")
    70  	}
    71  }
    72  
    73  // enableClock enables the clock for this desired GPIO port.
    74  func (p GPIO) enableClock() {
    75  	switch p.Pin / 16 {
    76  	case 0:
    77  		stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOAEN
    78  	case 1:
    79  		stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOBEN
    80  	case 2:
    81  		stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOCEN
    82  	case 3:
    83  		stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIODEN
    84  	case 4:
    85  		stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOEEN
    86  	case 5:
    87  		stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOFEN
    88  	case 6:
    89  		stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOGEN
    90  	case 7:
    91  		stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOHEN
    92  	case 8:
    93  		stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOIEN
    94  	default:
    95  		panic("machine: unknown port")
    96  	}
    97  }
    98  
    99  // Configure this pin with the given configuration.
   100  func (p GPIO) Configure(config GPIOConfig) {
   101  	// Configure the GPIO pin.
   102  	p.enableClock()
   103  	port := p.getPort()
   104  	pin := p.Pin % 16
   105  	pos := pin * 2
   106  
   107  	if config.Mode == GPIO_INPUT_FLOATING {
   108  		port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_INPUT) << pos)))
   109  		port.PUPDR = stm32.RegValue((uint32(port.PUPDR)&^(0x3<<pos) | (uint32(GPIO_FLOATING) << pos)))
   110  	} else if config.Mode == GPIO_INPUT_PULLDOWN {
   111  		port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_INPUT) << pos)))
   112  		port.PUPDR = stm32.RegValue((uint32(port.PUPDR)&^(0x3<<pos) | (uint32(GPIO_PULL_DOWN) << pos)))
   113  	} else if config.Mode == GPIO_INPUT_PULLUP {
   114  		port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_INPUT) << pos)))
   115  		port.PUPDR = stm32.RegValue((uint32(port.PUPDR)&^(0x3<<pos) | (uint32(GPIO_PULL_UP) << pos)))
   116  	} else if config.Mode == GPIO_OUTPUT {
   117  		port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_GENERAL_OUTPUT) << pos)))
   118  		port.OSPEEDR = stm32.RegValue((uint32(port.OSPEEDR)&^(0x3<<pos) | (uint32(GPIO_SPEED_HI) << pos)))
   119  	} else if config.Mode == GPIO_UART_TX {
   120  		port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_ALTERNABTIVE) << pos)))
   121  		port.OSPEEDR = stm32.RegValue((uint32(port.OSPEEDR)&^(0x3<<pos) | (uint32(GPIO_SPEED_HI) << pos)))
   122  		port.PUPDR = stm32.RegValue((uint32(port.PUPDR)&^(0x3<<pos) | (uint32(GPIO_PULL_UP) << pos)))
   123  		p.setAltFunc(0x7)
   124  	} else if config.Mode == GPIO_UART_RX {
   125  		port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_ALTERNABTIVE) << pos)))
   126  		port.PUPDR = stm32.RegValue((uint32(port.PUPDR)&^(0x3<<pos) | (uint32(GPIO_FLOATING) << pos)))
   127  		p.setAltFunc(0x7)
   128  	}
   129  }
   130  
   131  func (p GPIO) setAltFunc(af uint32) {
   132  	port := p.getPort()
   133  	pin := p.Pin % 16
   134  	pos := pin * 4
   135  	if pin >= 8 {
   136  		port.AFRH = stm32.RegValue(uint32(port.AFRH)&^(0xF<<pos) | ((af & 0xF) << pos))
   137  	} else {
   138  		port.AFRL = stm32.RegValue(uint32(port.AFRL)&^(0xF<<pos) | ((af & 0xF) << pos))
   139  	}
   140  }
   141  
   142  // Set the pin to high or low.
   143  // Warning: only use this on an output pin!
   144  func (p GPIO) Set(high bool) {
   145  	port := p.getPort()
   146  	pin := p.Pin % 16
   147  	if high {
   148  		port.BSRR = 1 << pin
   149  	} else {
   150  		port.BSRR = 1 << (pin + 16)
   151  	}
   152  }
   153  
   154  // UART
   155  type UART struct {
   156  	Buffer *RingBuffer
   157  }
   158  
   159  var (
   160  	// Both UART0 and UART1 refer to USART2.
   161  	UART0 = UART{Buffer: NewRingBuffer()}
   162  	UART1 = &UART0
   163  )
   164  
   165  // Configure the UART.
   166  func (uart UART) Configure(config UARTConfig) {
   167  	// Default baud rate to 115200.
   168  	if config.BaudRate == 0 {
   169  		config.BaudRate = 115200
   170  	}
   171  
   172  	// pins
   173  	switch config.TX {
   174  	default:
   175  		// use standard TX/RX pins PA2 and PA3
   176  		GPIO{UART_TX_PIN}.Configure(GPIOConfig{Mode: GPIO_UART_TX})
   177  		GPIO{UART_RX_PIN}.Configure(GPIOConfig{Mode: GPIO_UART_RX})
   178  	}
   179  
   180  	// Enable USART2 clock
   181  	stm32.RCC.APB1ENR |= stm32.RCC_APB1ENR_USART2EN
   182  
   183  	/*
   184  	  Set baud rate(115200)
   185  	  OVER8 = 0, APB2 = 42mhz
   186  	  +----------+--------+
   187  	  | baudrate | BRR    |
   188  	  +----------+--------+
   189  	  | 1200     | 0x88B8 |
   190  	  | 2400     | 0x445C |
   191  	  | 9600     | 0x1117 |
   192  	  | 19200    | 0x88C  |
   193  	  | 38400    | 0x446  |
   194  	  | 57600    | 0x2D9  |
   195  	  | 115200   | 0x16D  |
   196  	  +----------+--------+
   197  	*/
   198  	stm32.USART2.BRR = 0x16c
   199  
   200  	// Enable USART2 port.
   201  	stm32.USART2.CR1 = stm32.USART_CR1_TE | stm32.USART_CR1_RE | stm32.USART_CR1_RXNEIE | stm32.USART_CR1_UE
   202  
   203  	// Enable RX IRQ.
   204  	arm.SetPriority(stm32.IRQ_USART2, 0xc0)
   205  	arm.EnableIRQ(stm32.IRQ_USART2)
   206  }
   207  
   208  // WriteByte writes a byte of data to the UART.
   209  func (uart UART) WriteByte(c byte) error {
   210  	stm32.USART2.DR = stm32.RegValue(c)
   211  
   212  	for (stm32.USART2.SR & stm32.USART_SR_TXE) == 0 {
   213  	}
   214  	return nil
   215  }
   216  
   217  //go:export USART2_IRQHandler
   218  func handleUSART2() {
   219  	UART1.Receive(byte((stm32.USART2.DR & 0xFF)))
   220  }