machine/atsamd21: implements UART0 using the SERCOM0 interface
Signed-off-by: Ron Evans <ron@hybridgroup.com>
Этот коммит содержится в:
родитель
683e2a66e1
коммит
65ea74bd84
3 изменённых файлов: 135 добавлений и 8 удалений
|
@ -8,6 +8,7 @@
|
|||
package machine
|
||||
|
||||
import (
|
||||
"device/arm"
|
||||
"device/sam"
|
||||
)
|
||||
|
||||
|
@ -54,7 +55,7 @@ func (p GPIO) Configure(config GPIOConfig) {
|
|||
p.setPMux(val | (GPIO_SERCOM << sam.PORT_PMUX0_PMUXE_Pos))
|
||||
}
|
||||
// enable port config
|
||||
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR)
|
||||
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR | sam.PORT_PINCFG0_INEN)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -294,3 +295,115 @@ func (p GPIO) setPinCfg(val sam.RegValue8) {
|
|||
sam.PORT.PINCFG0_31 = val
|
||||
}
|
||||
}
|
||||
|
||||
// UART
|
||||
var (
|
||||
// The first hardware serial port on the SAMD21. Uses the SERCOM0 interface.
|
||||
UART0 = &UART{}
|
||||
)
|
||||
|
||||
const (
|
||||
sampleRate16X = 16
|
||||
lsbFirst = 1
|
||||
sercomRXPad0 = 0
|
||||
sercomRXPad1 = 1
|
||||
sercomRXPad2 = 2
|
||||
sercomRXPad3 = 3
|
||||
sercomTXPad0 = 0 // Only for UART
|
||||
sercomTXPad2 = 1 // Only for UART
|
||||
sercomTXPad023 = 2 // Only for UART with TX on PAD0, RTS on PAD2 and CTS on PAD3
|
||||
)
|
||||
|
||||
// Configure the UART.
|
||||
func (uart UART) Configure(config UARTConfig) {
|
||||
// Default baud rate to 115200.
|
||||
if config.BaudRate == 0 {
|
||||
config.BaudRate = 115200
|
||||
}
|
||||
|
||||
// enable pins
|
||||
GPIO{UART_TX_PIN}.Configure(GPIOConfig{Mode: GPIO_SERCOM})
|
||||
GPIO{UART_RX_PIN}.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 {
|
||||
}
|
||||
|
||||
// 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) |
|
||||
(1 << sam.SERCOM_USART_CTRLA_SAMPR_Pos) // sample rate of 16x
|
||||
|
||||
// Set baud rate
|
||||
uart.SetBaudRate(config.BaudRate)
|
||||
|
||||
// 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
|
||||
(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
|
||||
(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)
|
||||
|
||||
// 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)
|
||||
|
||||
// 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 {
|
||||
}
|
||||
|
||||
// setup interrupt on receive
|
||||
sam.SERCOM0_USART.INTENSET = sam.SERCOM_USART_INTENSET_RXC
|
||||
|
||||
// Enable RX IRQ.
|
||||
//arm.SetPriority(sam.IRQ_SERCOM0, 0xc0)
|
||||
arm.EnableIRQ(sam.IRQ_SERCOM0)
|
||||
}
|
||||
|
||||
// SetBaudRate sets the communication speed for the UART.
|
||||
func (uart UART) SetBaudRate(br uint32) {
|
||||
// Asynchronous fractional mode (Table 24-2 in datasheet)
|
||||
// BAUD = fref / (sampleRateValue * fbaud)
|
||||
// (multiply by 8, to calculate fractional piece)
|
||||
// uint32_t baudTimes8 = (SystemCoreClock * 8) / (16 * baudrate);
|
||||
baud := (CPU_FREQUENCY * 8) / (sampleRate16X * br)
|
||||
|
||||
// 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) |
|
||||
((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 {
|
||||
}
|
||||
sam.SERCOM0_USART.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
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// +build avr nrf stm32
|
||||
// +build avr nrf sam stm32
|
||||
|
||||
package machine
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ package runtime
|
|||
import (
|
||||
"device/arm"
|
||||
"device/sam"
|
||||
"machine"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
|
@ -21,16 +22,14 @@ func main() {
|
|||
func init() {
|
||||
initClocks()
|
||||
initRTC()
|
||||
initUARTClock()
|
||||
|
||||
// Turn on clock to SERCOM0 for Serial
|
||||
sam.PM.APBCMASK |= sam.PM_APBCMASK_SERCOM0_
|
||||
|
||||
// TODO: connect to UART
|
||||
// connect to UART
|
||||
machine.UART0.Configure(machine.UARTConfig{})
|
||||
}
|
||||
|
||||
func putchar(c byte) {
|
||||
// TODO: write byte to UART
|
||||
//machine.UART0.WriteByte(c)
|
||||
machine.UART0.WriteByte(c)
|
||||
}
|
||||
|
||||
func initClocks() {
|
||||
|
@ -216,6 +215,7 @@ func initRTC() {
|
|||
sam.RTC_MODE0.CTRL |= sam.RTC_MODE0_CTRL_ENABLE
|
||||
waitForSync()
|
||||
|
||||
arm.SetPriority(sam.IRQ_RTC, 0xc0)
|
||||
arm.EnableIRQ(sam.IRQ_RTC)
|
||||
}
|
||||
|
||||
|
@ -292,3 +292,17 @@ func handleRTC() {
|
|||
|
||||
timerWakeup = true
|
||||
}
|
||||
|
||||
func initUARTClock() {
|
||||
// Turn on clock to SERCOM0 for Serial
|
||||
sam.PM.APBCMASK |= sam.PM_APBCMASK_SERCOM0_
|
||||
|
||||
// Use GCLK0 for SERCOM0 aka UART0
|
||||
// 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_SERCOM0_CORE << sam.GCLK_CLKCTRL_ID_Pos) |
|
||||
(sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |
|
||||
sam.GCLK_CLKCTRL_CLKEN)
|
||||
waitForSync()
|
||||
}
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче