aboutsummaryrefslogtreecommitdiffstats
path: root/src/samd21/serial.c
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2018-07-27 19:22:44 -0400
committerKevin O'Connor <kevin@koconnor.net>2018-08-07 00:03:18 -0400
commit74cf4dc9e0fa129b315b398d8e70e4df20b26aea (patch)
tree6cb71cb9d79135bd1f850285bf3721e1f89022e2 /src/samd21/serial.c
parent71db5fbe316feb863b5c67bb7f9bb928c0decbe2 (diff)
downloadkutter-74cf4dc9e0fa129b315b398d8e70e4df20b26aea.tar.gz
kutter-74cf4dc9e0fa129b315b398d8e70e4df20b26aea.tar.xz
kutter-74cf4dc9e0fa129b315b398d8e70e4df20b26aea.zip
samd21: Initial support for SAMD21 micro-controllers
Add initial support for the Atmel SAMD21 micro-controllers. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'src/samd21/serial.c')
-rw-r--r--src/samd21/serial.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/src/samd21/serial.c b/src/samd21/serial.c
new file mode 100644
index 00000000..3c321e47
--- /dev/null
+++ b/src/samd21/serial.c
@@ -0,0 +1,61 @@
+// samd21 serial port
+//
+// Copyright (C) 2018 Kevin O'Connor <kevin@koconnor.net>
+//
+// This file may be distributed under the terms of the GNU GPLv3 license.
+
+#include "autoconf.h" // CONFIG_SERIAL_BAUD
+#include "board/serial_irq.h" // serial_rx_data
+#include "internal.h" // enable_pclock
+#include "samd21.h" // SERCOM0
+#include "sched.h" // DECL_INIT
+
+void
+serial_init(void)
+{
+ // Enable serial clock
+ enable_pclock(SERCOM0_GCLK_ID_CORE, PM_APBCMASK_SERCOM0);
+ // Enable pins
+ gpio_peripheral('A', 10, 'C', 0);
+ gpio_peripheral('A', 11, 'C', 0);
+ // Configure serial
+ SercomUsart *su = &SERCOM0->USART;
+ su->CTRLA.reg = 0;
+ uint32_t areg = (SERCOM_USART_CTRLA_MODE_USART_INT_CLK
+ | SERCOM_USART_CTRLA_DORD
+ | SERCOM_USART_CTRLA_SAMPR(1)
+ | SERCOM_USART_CTRLA_TXPO(1)
+ | SERCOM_USART_CTRLA_RXPO(3));
+ su->CTRLA.reg = areg;
+ su->CTRLB.reg = SERCOM_USART_CTRLB_TXEN | SERCOM_USART_CTRLB_RXEN;
+ uint32_t baud8 = CONFIG_CLOCK_FREQ / (2 * CONFIG_SERIAL_BAUD);
+ su->BAUD.reg = (SERCOM_USART_BAUD_FRAC_BAUD(baud8 / 8)
+ | SERCOM_USART_BAUD_FRAC_FP(baud8 % 8));
+ NVIC_SetPriority(SERCOM0_IRQn, 0);
+ NVIC_EnableIRQ(SERCOM0_IRQn);
+ su->INTENSET.reg = SERCOM_USART_INTENSET_RXC;
+ su->CTRLA.reg = areg | SERCOM_USART_CTRLA_ENABLE;
+}
+DECL_INIT(serial_init);
+
+void __visible
+SERCOM0_Handler(void)
+{
+ uint32_t status = SERCOM0->USART.INTFLAG.reg;
+ if (status & SERCOM_USART_INTFLAG_RXC)
+ serial_rx_byte(SERCOM0->USART.DATA.reg);
+ if (status & SERCOM_USART_INTFLAG_DRE) {
+ uint8_t data;
+ int ret = serial_get_tx_byte(&data);
+ if (ret)
+ SERCOM0->USART.INTENCLR.reg = SERCOM_USART_INTENSET_DRE;
+ else
+ SERCOM0->USART.DATA.reg = data;
+ }
+}
+
+void
+serial_enable_tx_irq(void)
+{
+ SERCOM0->USART.INTENSET.reg = SERCOM_USART_INTENSET_DRE;
+}