github.com/usbarmory/tamago@v0.0.0-20240508072735-8612bbe1e454/soc/sifive/uart/uart.go (about) 1 // SiFive UART driver 2 // https://github.com/usbarmory/tamago 3 // 4 // Copyright (c) WithSecure Corporation 5 // https://foundry.withsecure.com 6 // 7 // Use of this source code is governed by the license 8 // that can be found in the LICENSE file. 9 10 // Package uart implements a driver for SiFive UART controllers adopting the 11 // following reference specifications: 12 // - FU540C00RM - SiFive FU540-C000 Manual - v1p4 2021/03/25 13 // 14 // This package is only meant to be used with `GOOS=tamago GOARCH=riscv64` as 15 // supported by the TamaGo framework for bare metal Go on RISC-V SoCs, see 16 // https://github.com/usbarmory/tamago. 17 package uart 18 19 import ( 20 "github.com/usbarmory/tamago/bits" 21 "github.com/usbarmory/tamago/internal/reg" 22 ) 23 24 // UART registers 25 const ( 26 UART_DEFAULT_BAUDRATE = 115200 27 28 // p94, Chapter 13 UART, FU540C00RM 29 30 UARTx_TXDATA = 0x0000 31 TXDATA_FULL = 31 32 TXDATA_DATA = 0 33 34 UARTx_RXDATA = 0x0004 35 RXDATA_EMPTY = 31 36 RXDATA_DATA = 0 37 38 UARTx_TXCTRL = 0x0008 39 UARTx_RXCTRL = 0x000c 40 ) 41 42 // UART represents a serial port instance. 43 type UART struct { 44 // Controller index 45 Index int 46 // Base register 47 Base uint32 48 49 // control registers 50 txdata uint32 51 rxdata uint32 52 txctrl uint32 53 rxctrl uint32 54 } 55 56 // Init initializes and enables the UART for RS-232 mode, 57 // p3605, 55.13.1 Programming the UART in RS-232 mode, IMX6ULLRM. 58 func (hw *UART) Init() { 59 if hw.Base == 0 { 60 panic("invalid UART controller instance") 61 } 62 63 hw.txdata = hw.Base + UARTx_TXDATA 64 hw.rxdata = hw.Base + UARTx_RXDATA 65 hw.txctrl = hw.Base + UARTx_TXCTRL 66 hw.rxctrl = hw.Base + UARTx_RXCTRL 67 } 68 69 func (hw *UART) txFull() bool { 70 return reg.Get(hw.txdata, TXDATA_FULL, 1) == 1 71 } 72 73 // Tx transmits a single character to the serial port. 74 func (hw *UART) Tx(c byte) { 75 for hw.txFull() { 76 // wait for TX FIFO to have room for a character 77 } 78 reg.Write(hw.txdata, uint32(c)) 79 } 80 81 // Rx receives a single character from the serial port. 82 func (hw *UART) Rx() (c byte, valid bool) { 83 rxdata := reg.Read(hw.rxdata) 84 85 if bits.Get(&rxdata, RXDATA_EMPTY, 1) == 1 { 86 return 87 } 88 89 return byte(bits.Get(&rxdata, RXDATA_DATA, 0xff)), true 90 } 91 92 // Write data from buffer to serial port. 93 func (hw *UART) Write(buf []byte) (n int, _ error) { 94 for n = 0; n < len(buf); n++ { 95 hw.Tx(buf[n]) 96 } 97 98 return 99 } 100 101 // Read available data to buffer from serial port. 102 func (hw *UART) Read(buf []byte) (n int, _ error) { 103 var valid bool 104 105 for n = 0; n < len(buf); n++ { 106 buf[n], valid = hw.Rx() 107 108 if !valid { 109 break 110 } 111 } 112 113 return 114 }