mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-03 02:27:48 +00:00
96e863f0f3
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.
91 lines
2.3 KiB
Go
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)
|
|
}
|