Add core support for multiple UARTs (#152)
* machine/uart: add core support for multiple UARTs by allowing for multiple RingBuffers * machine/uart: complete core support for multiple UARTs * machine/uart: no need to store pointer to UART, better to treat like I2C and SPI * machine/uart: increase ring buffer size to 128 bytes * machine/uart: improve godocs comments and use comma-ok idiom for buffer Put/Get methods
Этот коммит содержится в:
родитель
d820c36c4f
коммит
4f4d7976c6
12 изменённых файлов: 216 добавлений и 77 удалений
|
@ -7,27 +7,34 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// change these to test a different UART or pins if available
|
||||
var (
|
||||
uart = machine.UART0
|
||||
tx uint8 = machine.UART_TX_PIN
|
||||
rx uint8 = machine.UART_RX_PIN
|
||||
)
|
||||
|
||||
func main() {
|
||||
machine.UART0.Configure(machine.UARTConfig{})
|
||||
machine.UART0.Write([]byte("Echo console enabled. Type something then press enter:\r\n"))
|
||||
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
|
||||
uart.Write([]byte("Echo console enabled. Type something then press enter:\r\n"))
|
||||
|
||||
input := make([]byte, 64)
|
||||
i := 0
|
||||
for {
|
||||
if machine.UART0.Buffered() > 0 {
|
||||
data, _ := machine.UART0.ReadByte()
|
||||
if uart.Buffered() > 0 {
|
||||
data, _ := uart.ReadByte()
|
||||
|
||||
switch data {
|
||||
case 13:
|
||||
// return key
|
||||
machine.UART0.Write([]byte("\r\n"))
|
||||
machine.UART0.Write([]byte("You typed: "))
|
||||
machine.UART0.Write(input[:i])
|
||||
machine.UART0.Write([]byte("\r\n"))
|
||||
uart.Write([]byte("\r\n"))
|
||||
uart.Write([]byte("You typed: "))
|
||||
uart.Write(input[:i])
|
||||
uart.Write([]byte("\r\n"))
|
||||
i = 0
|
||||
default:
|
||||
// just echo the character
|
||||
machine.UART0.WriteByte(data)
|
||||
uart.WriteByte(data)
|
||||
input[i] = data
|
||||
i++
|
||||
}
|
||||
|
|
|
@ -16,3 +16,9 @@ const (
|
|||
ADC4 = 4 // Used by TWI for SDA
|
||||
ADC5 = 5 // Used by TWI for SCL
|
||||
)
|
||||
|
||||
// UART pins
|
||||
const (
|
||||
UART_TX_PIN = 1
|
||||
UART_RX_PIN = 0
|
||||
)
|
||||
|
|
|
@ -4,8 +4,8 @@ package machine
|
|||
|
||||
// GPIO Pins
|
||||
const (
|
||||
D0 = 11 // RX: SERCOM0/PAD[3]
|
||||
D1 = 10 // TX: SERCOM0/PAD[2]
|
||||
D0 = 11 // UART0 RX: SERCOM0/PAD[3]
|
||||
D1 = 10 // UART0 TX: SERCOM0/PAD[2]
|
||||
D2 = 14
|
||||
D3 = 9
|
||||
D4 = 8
|
||||
|
@ -14,8 +14,8 @@ const (
|
|||
D7 = 21
|
||||
D8 = 6
|
||||
D9 = 7
|
||||
D10 = 18
|
||||
D11 = 16
|
||||
D10 = 18 // UART1 TX(1): SERCOM1/PAD[2] can be used for UART1 TX
|
||||
D11 = 16 // UART1 TX(2): SERCOM1/PAD[0] can be used for UART1 TX
|
||||
D12 = 19
|
||||
D13 = 17
|
||||
)
|
||||
|
|
49
src/machine/buffer.go
Обычный файл
49
src/machine/buffer.go
Обычный файл
|
@ -0,0 +1,49 @@
|
|||
package machine
|
||||
|
||||
const bufferSize = 128
|
||||
|
||||
//go:volatile
|
||||
type volatileByte byte
|
||||
|
||||
// RingBuffer is ring buffer implementation inspired by post at
|
||||
// https://www.embeddedrelated.com/showthread/comp.arch.embedded/77084-1.php
|
||||
//
|
||||
// It has some limitations currently due to how "volatile" variables that are
|
||||
// members of a struct are not compiled correctly by TinyGo.
|
||||
// See https://github.com/aykevl/tinygo/issues/151 for details.
|
||||
type RingBuffer struct {
|
||||
rxbuffer [bufferSize]volatileByte
|
||||
head volatileByte
|
||||
tail volatileByte
|
||||
}
|
||||
|
||||
// NewRingBuffer returns a new ring buffer.
|
||||
func NewRingBuffer() *RingBuffer {
|
||||
return &RingBuffer{}
|
||||
}
|
||||
|
||||
// Used returns how many bytes in buffer have been used.
|
||||
func (rb *RingBuffer) Used() uint8 {
|
||||
return uint8(rb.head - rb.tail)
|
||||
}
|
||||
|
||||
// Put stores a byte in the buffer. If the buffer is already
|
||||
// full, the method will return false.
|
||||
func (rb *RingBuffer) Put(val byte) bool {
|
||||
if rb.Used() != bufferSize {
|
||||
rb.head++
|
||||
rb.rxbuffer[rb.head%bufferSize] = volatileByte(val)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Get returns a byte from the buffer. If the buffer is empty,
|
||||
// the method will return a false as the second value.
|
||||
func (rb *RingBuffer) Get() (byte, bool) {
|
||||
if rb.Used() != 0 {
|
||||
rb.tail++
|
||||
return byte(rb.rxbuffer[rb.tail%bufferSize]), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
|
@ -211,6 +211,11 @@ func (i2c I2C) readByte() byte {
|
|||
return byte(*avr.TWDR)
|
||||
}
|
||||
|
||||
// UART on the AVR.
|
||||
type UART struct {
|
||||
Buffer *RingBuffer
|
||||
}
|
||||
|
||||
// Configure the UART on the AVR. Defaults to 9600 baud on Arduino.
|
||||
func (uart UART) Configure(config UARTConfig) {
|
||||
if config.BaudRate == 0 {
|
||||
|
@ -248,6 +253,6 @@ func handleUSART_RX() {
|
|||
// Ensure no error.
|
||||
if (*avr.UCSR0A & (avr.UCSR0A_FE0 | avr.UCSR0A_DOR0 | avr.UCSR0A_UPE0)) == 0 {
|
||||
// Put data from UDR register into buffer.
|
||||
bufferPut(byte(data))
|
||||
UART0.Receive(byte(data))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -297,10 +297,18 @@ func (p GPIO) setPinCfg(val sam.RegValue8) {
|
|||
}
|
||||
}
|
||||
|
||||
// UART
|
||||
// UART on the SAMD21.
|
||||
type UART struct {
|
||||
Buffer *RingBuffer
|
||||
Bus *sam.SERCOM_USART_Type
|
||||
}
|
||||
|
||||
var (
|
||||
// The first hardware serial port on the SAMD21. Uses the SERCOM0 interface.
|
||||
UART0 = &UART{}
|
||||
UART0 = UART{Bus: sam.SERCOM0_USART, Buffer: NewRingBuffer()}
|
||||
|
||||
// The second hardware serial port on the SAMD21. Uses the SERCOM1 interface.
|
||||
UART1 = UART{Bus: sam.SERCOM1_USART, Buffer: NewRingBuffer()}
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -322,20 +330,55 @@ func (uart UART) Configure(config UARTConfig) {
|
|||
config.BaudRate = 115200
|
||||
}
|
||||
|
||||
// enable pins
|
||||
GPIO{UART_TX_PIN}.Configure(GPIOConfig{Mode: GPIO_SERCOM})
|
||||
GPIO{UART_RX_PIN}.Configure(GPIOConfig{Mode: GPIO_SERCOM})
|
||||
// determine pins
|
||||
if config.TX == 0 {
|
||||
// use default pins
|
||||
config.TX = UART_TX_PIN
|
||||
config.RX = UART_RX_PIN
|
||||
}
|
||||
|
||||
// determine pads
|
||||
var txpad, rxpad int
|
||||
switch config.TX {
|
||||
case UART_TX_PIN:
|
||||
txpad = sercomTXPad2
|
||||
case D10:
|
||||
txpad = sercomTXPad2
|
||||
case D11:
|
||||
txpad = sercomTXPad0
|
||||
default:
|
||||
panic("Invalid TX pin for UART")
|
||||
}
|
||||
|
||||
switch config.RX {
|
||||
case UART_RX_PIN:
|
||||
rxpad = sercomRXPad3
|
||||
case D10:
|
||||
rxpad = sercomRXPad2
|
||||
case D11:
|
||||
rxpad = sercomRXPad0
|
||||
case D12:
|
||||
rxpad = sercomRXPad3
|
||||
case D13:
|
||||
rxpad = sercomRXPad1
|
||||
default:
|
||||
panic("Invalid RX pin for UART")
|
||||
}
|
||||
|
||||
// configure pins
|
||||
GPIO{config.TX}.Configure(GPIOConfig{Mode: GPIO_SERCOM})
|
||||
GPIO{config.RX}.Configure(GPIOConfig{Mode: GPIO_SERCOM})
|
||||
|
||||
// reset SERCOM0
|
||||
sam.SERCOM0_USART.CTRLA |= sam.SERCOM_USART_CTRLA_SWRST
|
||||
for (sam.SERCOM0_USART.CTRLA&sam.SERCOM_USART_CTRLA_SWRST) > 0 ||
|
||||
(sam.SERCOM0_USART.SYNCBUSY&sam.SERCOM_USART_SYNCBUSY_SWRST) > 0 {
|
||||
uart.Bus.CTRLA |= sam.SERCOM_USART_CTRLA_SWRST
|
||||
for (uart.Bus.CTRLA&sam.SERCOM_USART_CTRLA_SWRST) > 0 ||
|
||||
(uart.Bus.SYNCBUSY&sam.SERCOM_USART_SYNCBUSY_SWRST) > 0 {
|
||||
}
|
||||
|
||||
// set UART mode/sample rate
|
||||
// SERCOM_USART_CTRLA_MODE(mode) |
|
||||
// SERCOM_USART_CTRLA_SAMPR(sampleRate);
|
||||
sam.SERCOM0_USART.CTRLA = (sam.SERCOM_USART_CTRLA_MODE_USART_INT_CLK << sam.SERCOM_USART_CTRLA_MODE_Pos) |
|
||||
uart.Bus.CTRLA = (sam.SERCOM_USART_CTRLA_MODE_USART_INT_CLK << sam.SERCOM_USART_CTRLA_MODE_Pos) |
|
||||
(1 << sam.SERCOM_USART_CTRLA_SAMPR_Pos) // sample rate of 16x
|
||||
|
||||
// Set baud rate
|
||||
|
@ -344,39 +387,44 @@ func (uart UART) Configure(config UARTConfig) {
|
|||
// setup UART frame
|
||||
// SERCOM_USART_CTRLA_FORM( (parityMode == SERCOM_NO_PARITY ? 0 : 1) ) |
|
||||
// dataOrder << SERCOM_USART_CTRLA_DORD_Pos;
|
||||
sam.SERCOM0_USART.CTRLA |= (0 << sam.SERCOM_USART_CTRLA_FORM_Pos) | // no parity
|
||||
uart.Bus.CTRLA |= (0 << sam.SERCOM_USART_CTRLA_FORM_Pos) | // no parity
|
||||
(lsbFirst << sam.SERCOM_USART_CTRLA_DORD_Pos) // data order
|
||||
|
||||
// set UART stop bits/parity
|
||||
// SERCOM_USART_CTRLB_CHSIZE(charSize) |
|
||||
// nbStopBits << SERCOM_USART_CTRLB_SBMODE_Pos |
|
||||
// (parityMode == SERCOM_NO_PARITY ? 0 : parityMode) << SERCOM_USART_CTRLB_PMODE_Pos; //If no parity use default value
|
||||
sam.SERCOM0_USART.CTRLB |= (0 << sam.SERCOM_USART_CTRLB_CHSIZE_Pos) | // 8 bits is 0
|
||||
uart.Bus.CTRLB |= (0 << sam.SERCOM_USART_CTRLB_CHSIZE_Pos) | // 8 bits is 0
|
||||
(0 << sam.SERCOM_USART_CTRLB_SBMODE_Pos) | // 1 stop bit is zero
|
||||
(0 << sam.SERCOM_USART_CTRLB_PMODE_Pos) // no parity
|
||||
|
||||
// set UART pads. This is not same as pins...
|
||||
// SERCOM_USART_CTRLA_TXPO(txPad) |
|
||||
// SERCOM_USART_CTRLA_RXPO(rxPad);
|
||||
sam.SERCOM0_USART.CTRLA |= (sercomTXPad2 << sam.SERCOM_USART_CTRLA_TXPO_Pos) |
|
||||
(sercomRXPad3 << sam.SERCOM_USART_CTRLA_RXPO_Pos)
|
||||
uart.Bus.CTRLA |= sam.RegValue((txpad << sam.SERCOM_USART_CTRLA_TXPO_Pos) |
|
||||
(rxpad << sam.SERCOM_USART_CTRLA_RXPO_Pos))
|
||||
|
||||
// Enable Transceiver and Receiver
|
||||
//sercom->USART.CTRLB.reg |= SERCOM_USART_CTRLB_TXEN | SERCOM_USART_CTRLB_RXEN ;
|
||||
sam.SERCOM0_USART.CTRLB |= (sam.SERCOM_USART_CTRLB_TXEN | sam.SERCOM_USART_CTRLB_RXEN)
|
||||
uart.Bus.CTRLB |= (sam.SERCOM_USART_CTRLB_TXEN | sam.SERCOM_USART_CTRLB_RXEN)
|
||||
|
||||
// Enable USART1 port.
|
||||
// sercom->USART.CTRLA.bit.ENABLE = 0x1u;
|
||||
sam.SERCOM0_USART.CTRLA |= sam.SERCOM_USART_CTRLA_ENABLE
|
||||
for (sam.SERCOM0_USART.SYNCBUSY & sam.SERCOM_USART_SYNCBUSY_ENABLE) > 0 {
|
||||
uart.Bus.CTRLA |= sam.SERCOM_USART_CTRLA_ENABLE
|
||||
for (uart.Bus.SYNCBUSY & sam.SERCOM_USART_SYNCBUSY_ENABLE) > 0 {
|
||||
}
|
||||
|
||||
// setup interrupt on receive
|
||||
sam.SERCOM0_USART.INTENSET = sam.SERCOM_USART_INTENSET_RXC
|
||||
uart.Bus.INTENSET = sam.SERCOM_USART_INTENSET_RXC
|
||||
|
||||
// Enable RX IRQ.
|
||||
//arm.SetPriority(sam.IRQ_SERCOM0, 0xc0)
|
||||
if config.TX == UART_TX_PIN {
|
||||
// UART0
|
||||
arm.EnableIRQ(sam.IRQ_SERCOM0)
|
||||
} else {
|
||||
// UART1
|
||||
arm.EnableIRQ(sam.IRQ_SERCOM1)
|
||||
}
|
||||
}
|
||||
|
||||
// SetBaudRate sets the communication speed for the UART.
|
||||
|
@ -389,24 +437,31 @@ func (uart UART) SetBaudRate(br uint32) {
|
|||
|
||||
// sercom->USART.BAUD.FRAC.FP = (baudTimes8 % 8);
|
||||
// sercom->USART.BAUD.FRAC.BAUD = (baudTimes8 / 8);
|
||||
sam.SERCOM0_USART.BAUD = sam.RegValue16(((baud % 8) << sam.SERCOM_USART_BAUD_FRAC_MODE_FP_Pos) |
|
||||
uart.Bus.BAUD = sam.RegValue16(((baud % 8) << sam.SERCOM_USART_BAUD_FRAC_MODE_FP_Pos) |
|
||||
((baud / 8) << sam.SERCOM_USART_BAUD_FRAC_MODE_BAUD_Pos))
|
||||
}
|
||||
|
||||
// WriteByte writes a byte of data to the UART.
|
||||
func (uart UART) WriteByte(c byte) error {
|
||||
// wait until ready to receive
|
||||
for (sam.SERCOM0_USART.INTFLAG & sam.SERCOM_USART_INTFLAG_DRE) == 0 {
|
||||
for (uart.Bus.INTFLAG & sam.SERCOM_USART_INTFLAG_DRE) == 0 {
|
||||
}
|
||||
sam.SERCOM0_USART.DATA = sam.RegValue16(c)
|
||||
uart.Bus.DATA = sam.RegValue16(c)
|
||||
return nil
|
||||
}
|
||||
|
||||
//go:export SERCOM0_IRQHandler
|
||||
func handleUART0() {
|
||||
// should reset IRQ
|
||||
bufferPut(byte((sam.SERCOM0_USART.DATA & 0xFF)))
|
||||
sam.SERCOM0_USART.INTFLAG |= sam.SERCOM_USART_INTFLAG_RXC
|
||||
UART0.Receive(byte((UART0.Bus.DATA & 0xFF)))
|
||||
UART0.Bus.INTFLAG |= sam.SERCOM_USART_INTFLAG_RXC
|
||||
}
|
||||
|
||||
//go:export SERCOM1_IRQHandler
|
||||
func handleUART1() {
|
||||
// should reset IRQ
|
||||
UART1.Receive(byte((UART1.Bus.DATA & 0xFF)))
|
||||
UART1.Bus.INTFLAG |= sam.SERCOM_USART_INTFLAG_RXC
|
||||
}
|
||||
|
||||
// I2C on the SAMD21.
|
||||
|
|
|
@ -25,6 +25,12 @@ func (p GPIO) Get() bool {
|
|||
return (val > 0)
|
||||
}
|
||||
|
||||
// UART on the AVR is a dummy implementation. UART has not been implemented for ATtiny
|
||||
// devices.
|
||||
type UART struct {
|
||||
Buffer *RingBuffer
|
||||
}
|
||||
|
||||
// Configure is a dummy implementation. UART has not been implemented for ATtiny
|
||||
// devices.
|
||||
func (uart UART) Configure(config UARTConfig) {
|
||||
|
|
|
@ -92,5 +92,5 @@ var I2C0 = I2C{}
|
|||
// UART
|
||||
var (
|
||||
// UART0 is the hardware serial port on the AVR.
|
||||
UART0 = &UART{}
|
||||
UART0 = UART{Buffer: NewRingBuffer()}
|
||||
)
|
||||
|
|
|
@ -54,10 +54,15 @@ func (p GPIO) Get() bool {
|
|||
return (port.IN>>pin)&1 != 0
|
||||
}
|
||||
|
||||
// UART on the NRF.
|
||||
type UART struct {
|
||||
Buffer *RingBuffer
|
||||
}
|
||||
|
||||
// UART
|
||||
var (
|
||||
// UART0 is the hardware serial port on the NRF.
|
||||
UART0 = &UART{}
|
||||
UART0 = UART{Buffer: NewRingBuffer()}
|
||||
)
|
||||
|
||||
// Configure the UART.
|
||||
|
@ -108,7 +113,7 @@ func (uart UART) WriteByte(c byte) error {
|
|||
|
||||
func (uart UART) handleInterrupt() {
|
||||
if nrf.UART0.EVENTS_RXDRDY != 0 {
|
||||
bufferPut(byte(nrf.UART0.RXD))
|
||||
uart.Receive(byte(nrf.UART0.RXD))
|
||||
nrf.UART0.EVENTS_RXDRDY = 0x0
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,11 +100,15 @@ func (p GPIO) Set(high bool) {
|
|||
}
|
||||
|
||||
// UART
|
||||
type UART struct {
|
||||
Buffer *RingBuffer
|
||||
}
|
||||
|
||||
var (
|
||||
// USART1 is the first hardware serial port on the STM32.
|
||||
// Both UART0 and UART1 refers to USART1.
|
||||
UART0 = &UART{}
|
||||
UART1 = UART0
|
||||
// Both UART0 and UART1 refer to USART1.
|
||||
UART0 = UART{Buffer: NewRingBuffer()}
|
||||
UART1 = &UART0
|
||||
)
|
||||
|
||||
// Configure the UART.
|
||||
|
@ -160,7 +164,7 @@ func (uart UART) WriteByte(c byte) error {
|
|||
|
||||
//go:export USART1_IRQHandler
|
||||
func handleUART1() {
|
||||
bufferPut(byte((stm32.USART1.DR & 0xFF)))
|
||||
UART1.Receive(byte((stm32.USART1.DR & 0xFF)))
|
||||
}
|
||||
|
||||
// SPI on the STM32.
|
||||
|
|
|
@ -10,8 +10,19 @@ type UARTConfig struct {
|
|||
RX uint8
|
||||
}
|
||||
|
||||
type UART struct {
|
||||
}
|
||||
// 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) {
|
||||
|
@ -47,41 +58,20 @@ func (uart UART) Write(data []byte) (n int, err error) {
|
|||
// If there is no data in the buffer, returns an error.
|
||||
func (uart UART) ReadByte() (byte, error) {
|
||||
// check if RX buffer is empty
|
||||
if uart.Buffered() == 0 {
|
||||
buf, ok := uart.Buffer.Get()
|
||||
if !ok {
|
||||
return 0, errors.New("Buffer empty")
|
||||
}
|
||||
|
||||
return bufferGet(), nil
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
// Buffered returns the number of bytes currently stored in the RX buffer.
|
||||
func (uart UART) Buffered() int {
|
||||
return int(bufferUsed())
|
||||
return int(uart.Buffer.Used())
|
||||
}
|
||||
|
||||
const bufferSize = 64
|
||||
|
||||
// Minimal ring buffer implementation inspired by post at
|
||||
// https://www.embeddedrelated.com/showthread/comp.arch.embedded/77084-1.php
|
||||
|
||||
//go:volatile
|
||||
type volatileByte byte
|
||||
|
||||
var rxbuffer [bufferSize]volatileByte
|
||||
var head volatileByte
|
||||
var tail volatileByte
|
||||
|
||||
func bufferUsed() uint8 { return uint8(head - tail) }
|
||||
func bufferPut(val byte) {
|
||||
if bufferUsed() != bufferSize {
|
||||
head++
|
||||
rxbuffer[head%bufferSize] = volatileByte(val)
|
||||
}
|
||||
}
|
||||
func bufferGet() byte {
|
||||
if bufferUsed() != 0 {
|
||||
tail++
|
||||
return byte(rxbuffer[tail%bufferSize])
|
||||
}
|
||||
return 0
|
||||
// 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)
|
||||
}
|
||||
|
|
|
@ -297,7 +297,7 @@ func handleRTC() {
|
|||
}
|
||||
|
||||
func initUARTClock() {
|
||||
// Turn on clock to SERCOM0 for Serial
|
||||
// Turn on clock to SERCOM0 for UART0
|
||||
sam.PM.APBCMASK |= sam.PM_APBCMASK_SERCOM0_
|
||||
|
||||
// Use GCLK0 for SERCOM0 aka UART0
|
||||
|
@ -308,6 +308,18 @@ func initUARTClock() {
|
|||
(sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |
|
||||
sam.GCLK_CLKCTRL_CLKEN)
|
||||
waitForSync()
|
||||
|
||||
// Turn on clock to SERCOM1 for UART1
|
||||
sam.PM.APBCMASK |= sam.PM_APBCMASK_SERCOM1_
|
||||
|
||||
// Use GCLK0 for SERCOM1 aka UART1
|
||||
// GCLK_CLKCTRL_ID( clockId ) | // Generic Clock 0 (SERCOMx)
|
||||
// GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
|
||||
// GCLK_CLKCTRL_CLKEN ;
|
||||
sam.GCLK.CLKCTRL = sam.RegValue16((sam.GCLK_CLKCTRL_ID_SERCOM1_CORE << sam.GCLK_CLKCTRL_ID_Pos) |
|
||||
(sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |
|
||||
sam.GCLK_CLKCTRL_CLKEN)
|
||||
waitForSync()
|
||||
}
|
||||
|
||||
func initI2CClock() {
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче