diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2018-07-27 19:22:44 -0400 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2018-08-07 00:03:18 -0400 |
commit | 74cf4dc9e0fa129b315b398d8e70e4df20b26aea (patch) | |
tree | 6cb71cb9d79135bd1f850285bf3721e1f89022e2 /src/samd21/serial.c | |
parent | 71db5fbe316feb863b5c67bb7f9bb928c0decbe2 (diff) | |
download | kutter-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.c | 61 |
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; +} |