samd: uart support

This commit is contained in:
Jason Kotzin 2018-07-12 15:50:04 -07:00
parent d62d82bb2f
commit 58865ca5ec
7 changed files with 143 additions and 25 deletions

2
.gitignore vendored
View File

@ -16,4 +16,4 @@ tags
*.b#*
blackmagic_upgrade
*.exe
.DS_Store

@ -1 +1 @@
Subproject commit 16df5b57b8f7d80e7344188ba1a8484930a32afe
Subproject commit a6405c6f2a3383173ad5da40ea167e206d950ad1

View File

@ -45,6 +45,7 @@ main(int argc, char **argv)
volatile struct exception e;
TRY_CATCH(e, EXCEPTION_ALL) {
gdb_main();
uart_pop();
}
if (e.type) {
gdb_putpacketz("EFF");

View File

@ -52,7 +52,9 @@ void sys_tick_handler(void)
if(running_status)
gpio_toggle(LED_PORT, LED_IDLE_RUN);
time_ms += 10;
time_ms += 1;
uart_pop();
}
uint32_t platform_time_ms(void)
@ -79,7 +81,7 @@ static uint32_t timing_init(void)
uint32_t cal = 0;
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB);
systick_set_reload(480000); /* Interrupt us at 10 Hz */
systick_set_reload(48000); /* Interrupt us at 10 Hz */
systick_interrupt_enable();
systick_counter_enable();
@ -110,11 +112,12 @@ void platform_init(void)
gpio_config_output(SRST_PORT, SRST_PIN, GPIO_OUT_FLAG_DEFAULT_HIGH);
gpio_set(SRST_PORT, SRST_PIN);
/* setup uart led, disable by default*/
gpio_config_output(LED_PORT_UART, LED_UART, 0);//GPIO_OUT_FLAG_DEFAULT_HIGH);
gpio_clear(LED_PORT_UART, LED_UART);
timing_init();
//nvic_enable_irq(NVIC_UART0_IRQ);
//usbuart_init();
usbuart_init();
cdcacm_init();
}

View File

@ -47,13 +47,13 @@ extern uint8_t running_status;
#define TMS_PIN GPIO7
#define TCK_PORT PORTA
#define TCK_PIN GPIO8
#define TCK_PIN GPIO5
#define TDI_PORT PORTA
#define TDI_PIN GPIO5
#define TDI_PIN GPIO3
#define TDO_PORT PORTA
#define TDO_PIN GPIO4
#define TDO_PIN GPIO2
#define SWO_PORT PORTA
#define SWO_PIN GPIO6
@ -68,6 +68,9 @@ extern uint8_t running_status;
#define SRST_PORT PORTA
#define SRST_PIN GPIO6
#define LED_PORT_UART PORTA
#define LED_UART GPIO12
#else
#define LED_PORT PORTA
@ -98,6 +101,10 @@ extern uint8_t running_status;
#define SRST_PORT PORTA
#define SRST_PIN GPIO26
#define LED_PORT_UART PORTA
#define LED_UART GPIO12
#endif
#define TMS_SET_MODE() { \
@ -123,25 +130,25 @@ extern uint8_t running_status;
#define gpio_set_val(port, pin, val) do { \
if(val) \
gpio_set((port), (pin)); \
_gpio_set((port), (pin)); \
else \
gpio_clear((port), (pin)); \
_gpio_clear((port), (pin)); \
} while(0)
#ifdef INLINE_GPIO
static inline void _gpio_set(uint32_t gpioport, uint16_t gpios)
static inline void _gpio_set(uint32_t gpioport, uint32_t gpios)
{
PORT_OUTSET(gpioport) = gpios;
}
#define gpio_set _gpio_set
static inline void _gpio_clear(uint32_t gpioport, uint16_t gpios)
static inline void _gpio_clear(uint32_t gpioport, uint32_t gpios)
{
PORT_OUTCLR(gpioport) = gpios;
}
#define gpio_clear _gpio_clear
static inline uint16_t _gpio_get(uint32_t gpioport, uint16_t gpios)
static inline uint16_t _gpio_get(uint32_t gpioport, uint32_t gpios)
{
return (uint32_t)PORT_IN(gpioport) & gpios;
}
@ -158,4 +165,6 @@ static inline int platform_hwversion(void)
{
return 0;
}
void uart_pop(void);
#endif

View File

@ -40,4 +40,3 @@ jtagtap_next(const uint8_t dTMS, const uint8_t dTDI)
return ret != 0;
}

View File

@ -21,26 +21,105 @@
#include "general.h"
#include "cdcacm.h"
#include <libopencm3/sam/d/bitfield.h>
#include <libopencm3/sam/d/gclk.h>
#include <libopencm3/sam/d/pm.h>
#include <libopencm3/sam/d/port.h>
#include <libopencm3/sam/d/nvic.h>
#include <libopencm3/sam/d/uart.h>
#include <libopencm3/cm3/cortex.h>
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/cm3/scb.h>
#include <libopencm3/cm3/scs.h>
#include <libopencm3/cm3/systick.h>
#include <libopencm3/usb/usbd.h>
#include <libopencm3/usb/cdc.h>
#include "queue.h"
#define USART_NUM 0
#define Q_SIZE 1024
usbd_device * usbdev;
/* input and output ring buffer */
struct {
char buf[Q_SIZE];
volatile size_t head, tail;
} rx, tx;
/* non blocking putc function */
static void usart_putc(char c)
{
#ifndef CONSOLE_NO_AUTO_CRLF
if (c == '\n')
usart_putc('\r');
#endif
if (qfull(tx.head, tx.tail, Q_SIZE))
return;
cm_disable_interrupts();
tx.buf[tx.head] = c;
tx.head = qinc(tx.head, Q_SIZE);
cm_enable_interrupts();
/* kick the transmitter to restart interrupts */
usart_enable_tx_interrupt(USART_NUM);
}
void usbuart_init(void)
{
/* enable gpios */
gpio_config_special(PORTA, GPIO8, SOC_GPIO_PERIPH_C); /* tx pin */
gpio_config_special(PORTA, GPIO9, SOC_GPIO_PERIPH_C); /* rx pin */
/* enable clocking to sercom3 */
set_periph_clk(GCLK0, GCLK_ID_SERCOM0_CORE);
periph_clk_en(GCLK_ID_SERCOM0_CORE, 1);
usart_enable(USART_NUM, 115200);
usart_enable_rx_interrupt(USART_NUM);
usart_enable_tx_interrupt(USART_NUM);
}
void usbuart_set_line_coding(struct usb_cdc_line_coding *coding)
{
/* Not supported yet, only 115200 8bits/etc */
(void) coding;
}
void usbuart_usb_out_cb(usbd_device *dev, uint8_t ep)
{
(void) dev;
(void) ep;
(void)ep;
char buf[CDCACM_PACKET_SIZE];
int len = usbd_ep_read_packet(dev, CDCACM_UART_ENDPOINT,
buf, CDCACM_PACKET_SIZE);
gpio_set(LED_PORT_UART, LED_UART);
for(int i = 0; i < len; i++) {
usart_putc(buf[i]);
}
gpio_clear(LED_PORT_UART, LED_UART);
}
/* run by our systick timer */
void uart_pop(void)
{
if (cdcacm_get_config() != 1) {
return;
}
if (!qempty(rx.head, rx.tail)) {
if (usbd_ep_write_packet(usbdev, 0x83, &rx.buf[rx.tail], 1) == 0) {
return;
}
rx.tail = qinc(rx.tail, Q_SIZE);
}
}
void usbuart_usb_in_cb(usbd_device *dev, uint8_t ep)
{
@ -48,11 +127,38 @@ void usbuart_usb_in_cb(usbd_device *dev, uint8_t ep)
(void) ep;
}
/*
* Read a character from the UART RX and stuff it in a software FIFO.
* Allowed to read from FIFO out pointer, but not write to it.
* Allowed to write to FIFO in pointer.
*/
void USBUART_ISR(void)
/************************** UART Interrupt Handlers *************************/
static void uart_rx_irq(void)
{
char c = UART(USART_NUM)->data;
/* bug?, need to re-enable rx complete interrupt */
INSERTBF(UART_INTENSET_RXC, 1, UART(0)->intenset);
if (!qfull(rx.head, rx.tail, Q_SIZE)) {
rx.buf[rx.head] = c;
rx.head = qinc(rx.head, Q_SIZE);
}
}
static void uart_tx_irq(void)
{
if (!qempty(tx.head, tx.tail)) {
usart_send(USART_NUM, tx.buf[tx.tail]);
tx.tail = qinc(tx.tail, Q_SIZE);
} else {
usart_disable_tx_interrupt(USART_NUM);
}
}
void sercom0_isr(void)
{
/* Turn on LED */
gpio_set(LED_PORT_UART, LED_UART);
if (GETBF(UART_INTFLAG_RXC, UART(USART_NUM)->intflag))
uart_rx_irq();
if (GETBF(UART_INTFLAG_DRE, UART(USART_NUM)->intflag))
uart_tx_irq();
}