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

     1  //go:build stm32
     2  
     3  package machine
     4  
     5  // Peripheral abstraction layer for UARTs on the stm32 family.
     6  
     7  import (
     8  	"device/stm32"
     9  	"runtime/interrupt"
    10  	"runtime/volatile"
    11  	"unsafe"
    12  )
    13  
    14  // UART representation
    15  type UART struct {
    16  	Buffer            *RingBuffer
    17  	Bus               *stm32.USART_Type
    18  	Interrupt         interrupt.Interrupt
    19  	TxAltFuncSelector uint8
    20  	RxAltFuncSelector uint8
    21  
    22  	// Registers specific to the chip
    23  	rxReg       *volatile.Register32
    24  	txReg       *volatile.Register32
    25  	statusReg   *volatile.Register32
    26  	txEmptyFlag uint32
    27  }
    28  
    29  // Configure the UART.
    30  func (uart *UART) Configure(config UARTConfig) {
    31  	// Default baud rate to 115200.
    32  	if config.BaudRate == 0 {
    33  		config.BaudRate = 115200
    34  	}
    35  
    36  	// Set the GPIO pins to defaults if they're not set
    37  	if config.TX == 0 && config.RX == 0 {
    38  		config.TX = UART_TX_PIN
    39  		config.RX = UART_RX_PIN
    40  	}
    41  
    42  	// STM32 families have different, but compatible, registers for
    43  	// basic UART functions.  For each family populate the registers
    44  	// into `uart`.
    45  	uart.setRegisters()
    46  
    47  	// Enable USART clock
    48  	enableAltFuncClock(unsafe.Pointer(uart.Bus))
    49  
    50  	uart.configurePins(config)
    51  
    52  	// Set baud rate
    53  	uart.SetBaudRate(config.BaudRate)
    54  
    55  	// Enable USART port, tx, rx and rx interrupts
    56  	uart.Bus.CR1.Set(stm32.USART_CR1_TE | stm32.USART_CR1_RE | stm32.USART_CR1_RXNEIE | stm32.USART_CR1_UE)
    57  
    58  	// Enable RX IRQ
    59  	uart.Interrupt.SetPriority(0xc0)
    60  	uart.Interrupt.Enable()
    61  }
    62  
    63  // handleInterrupt should be called from the appropriate interrupt handler for
    64  // this UART instance.
    65  func (uart *UART) handleInterrupt(interrupt.Interrupt) {
    66  	uart.Receive(byte((uart.rxReg.Get() & 0xFF)))
    67  }
    68  
    69  // SetBaudRate sets the communication speed for the UART. Defer to chip-specific
    70  // routines for calculation
    71  func (uart *UART) SetBaudRate(br uint32) {
    72  	divider := uart.getBaudRateDivisor(br)
    73  	uart.Bus.BRR.Set(divider)
    74  }
    75  
    76  // WriteByte writes a byte of data to the UART.
    77  func (uart *UART) writeByte(c byte) error {
    78  	uart.txReg.Set(uint32(c))
    79  
    80  	for !uart.statusReg.HasBits(uart.txEmptyFlag) {
    81  	}
    82  	return nil
    83  }
    84  
    85  func (uart *UART) flush() {}