Files
tinygo/src/machine/uart.go
T
Ayke van Laethem 96e863f0f3 all: add a flag to the command line to select the serial implementation
This can be very useful for some purposes:

  * It makes it possible to disable the UART in cases where it is not
    needed or needs to be disabled to conserve power.
  * It makes it possible to disable the serial output to reduce code
    size, which may be important for some chips. Sometimes, a few kB can
    be saved this way.
  * It makes it possible to override the default, for example you might
    want to use an actual UART to debug the USB-CDC implementation.

It also lowers the dependency on having machine.Serial defined, which is
often not defined when targeting a chip. Eventually, we might want to
make it possible to write `-target=nrf52` or `-target=atmega328p` for
example to target the chip itself with no board specific assumptions.

The defaults don't change. I checked this by running `make smoketest`
before and after and comparing the results.
2021-06-25 17:58:39 +02:00

91 lines
2.3 KiB
Go

// +build atmega esp nrf sam sifive stm32 k210 nxp rp2040
package machine
import "errors"
var errUARTBufferEmpty = errors.New("UART buffer empty")
// UARTParity is the parity setting to be used for UART communication.
type UARTParity int
const (
// ParityNone means to not use any parity checking. This is
// the most common setting.
ParityNone UARTParity = 0
// ParityEven means to expect that the total number of 1 bits sent
// should be an even number.
ParityEven UARTParity = 1
// ParityOdd means to expect that the total number of 1 bits sent
// should be an odd number.
ParityOdd UARTParity = 2
)
// To implement the UART interface for a board, you must declare a concrete type as follows:
//
// type UART struct {
// Buffer *RingBuffer
// }
//
// You can also add additional members to this struct depending on your implementation,
// but the *RingBuffer is required.
// When you are declaring your UARTs for your board, make sure that you also declare the
// RingBuffer using the NewRingBuffer() function when you declare your UART:
//
// UART{Buffer: NewRingBuffer()}
//
// Read from the RX buffer.
func (uart *UART) Read(data []byte) (n int, err error) {
// check if RX buffer is empty
size := uart.Buffered()
if size == 0 {
return 0, nil
}
// Make sure we do not read more from buffer than the data slice can hold.
if len(data) < size {
size = len(data)
}
// only read number of bytes used from buffer
for i := 0; i < size; i++ {
v, _ := uart.ReadByte()
data[i] = v
}
return size, nil
}
// Write data to the UART.
func (uart *UART) Write(data []byte) (n int, err error) {
for _, v := range data {
uart.WriteByte(v)
}
return len(data), nil
}
// ReadByte reads a single byte from the RX buffer.
// If there is no data in the buffer, returns an error.
func (uart *UART) ReadByte() (byte, error) {
// check if RX buffer is empty
buf, ok := uart.Buffer.Get()
if !ok {
return 0, errUARTBufferEmpty
}
return buf, nil
}
// Buffered returns the number of bytes currently stored in the RX buffer.
func (uart *UART) Buffered() int {
return int(uart.Buffer.Used())
}
// Receive handles adding data to the UART's data buffer.
// Usually called by the IRQ handler for a machine.
func (uart *UART) Receive(data byte) {
uart.Buffer.Put(data)
}