samd: uart support
This commit is contained in:
parent
d62d82bb2f
commit
58865ca5ec
2
.gitignore
vendored
2
.gitignore
vendored
@ -16,4 +16,4 @@ tags
|
|||||||
*.b#*
|
*.b#*
|
||||||
blackmagic_upgrade
|
blackmagic_upgrade
|
||||||
*.exe
|
*.exe
|
||||||
|
.DS_Store
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 16df5b57b8f7d80e7344188ba1a8484930a32afe
|
Subproject commit a6405c6f2a3383173ad5da40ea167e206d950ad1
|
@ -45,6 +45,7 @@ main(int argc, char **argv)
|
|||||||
volatile struct exception e;
|
volatile struct exception e;
|
||||||
TRY_CATCH(e, EXCEPTION_ALL) {
|
TRY_CATCH(e, EXCEPTION_ALL) {
|
||||||
gdb_main();
|
gdb_main();
|
||||||
|
uart_pop();
|
||||||
}
|
}
|
||||||
if (e.type) {
|
if (e.type) {
|
||||||
gdb_putpacketz("EFF");
|
gdb_putpacketz("EFF");
|
||||||
|
@ -52,7 +52,9 @@ void sys_tick_handler(void)
|
|||||||
if(running_status)
|
if(running_status)
|
||||||
gpio_toggle(LED_PORT, LED_IDLE_RUN);
|
gpio_toggle(LED_PORT, LED_IDLE_RUN);
|
||||||
|
|
||||||
time_ms += 10;
|
time_ms += 1;
|
||||||
|
|
||||||
|
uart_pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t platform_time_ms(void)
|
uint32_t platform_time_ms(void)
|
||||||
@ -79,7 +81,7 @@ static uint32_t timing_init(void)
|
|||||||
uint32_t cal = 0;
|
uint32_t cal = 0;
|
||||||
|
|
||||||
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB);
|
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_interrupt_enable();
|
||||||
|
|
||||||
systick_counter_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_config_output(SRST_PORT, SRST_PIN, GPIO_OUT_FLAG_DEFAULT_HIGH);
|
||||||
gpio_set(SRST_PORT, SRST_PIN);
|
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();
|
timing_init();
|
||||||
|
usbuart_init();
|
||||||
//nvic_enable_irq(NVIC_UART0_IRQ);
|
|
||||||
//usbuart_init();
|
|
||||||
|
|
||||||
cdcacm_init();
|
cdcacm_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,13 +47,13 @@ extern uint8_t running_status;
|
|||||||
#define TMS_PIN GPIO7
|
#define TMS_PIN GPIO7
|
||||||
|
|
||||||
#define TCK_PORT PORTA
|
#define TCK_PORT PORTA
|
||||||
#define TCK_PIN GPIO8
|
#define TCK_PIN GPIO5
|
||||||
|
|
||||||
#define TDI_PORT PORTA
|
#define TDI_PORT PORTA
|
||||||
#define TDI_PIN GPIO5
|
#define TDI_PIN GPIO3
|
||||||
|
|
||||||
#define TDO_PORT PORTA
|
#define TDO_PORT PORTA
|
||||||
#define TDO_PIN GPIO4
|
#define TDO_PIN GPIO2
|
||||||
|
|
||||||
#define SWO_PORT PORTA
|
#define SWO_PORT PORTA
|
||||||
#define SWO_PIN GPIO6
|
#define SWO_PIN GPIO6
|
||||||
@ -68,6 +68,9 @@ extern uint8_t running_status;
|
|||||||
#define SRST_PORT PORTA
|
#define SRST_PORT PORTA
|
||||||
#define SRST_PIN GPIO6
|
#define SRST_PIN GPIO6
|
||||||
|
|
||||||
|
#define LED_PORT_UART PORTA
|
||||||
|
#define LED_UART GPIO12
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define LED_PORT PORTA
|
#define LED_PORT PORTA
|
||||||
@ -98,6 +101,10 @@ extern uint8_t running_status;
|
|||||||
|
|
||||||
#define SRST_PORT PORTA
|
#define SRST_PORT PORTA
|
||||||
#define SRST_PIN GPIO26
|
#define SRST_PIN GPIO26
|
||||||
|
|
||||||
|
#define LED_PORT_UART PORTA
|
||||||
|
#define LED_UART GPIO12
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TMS_SET_MODE() { \
|
#define TMS_SET_MODE() { \
|
||||||
@ -123,25 +130,25 @@ extern uint8_t running_status;
|
|||||||
|
|
||||||
#define gpio_set_val(port, pin, val) do { \
|
#define gpio_set_val(port, pin, val) do { \
|
||||||
if(val) \
|
if(val) \
|
||||||
gpio_set((port), (pin)); \
|
_gpio_set((port), (pin)); \
|
||||||
else \
|
else \
|
||||||
gpio_clear((port), (pin)); \
|
_gpio_clear((port), (pin)); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#ifdef INLINE_GPIO
|
#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;
|
PORT_OUTSET(gpioport) = gpios;
|
||||||
}
|
}
|
||||||
#define gpio_set _gpio_set
|
#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;
|
PORT_OUTCLR(gpioport) = gpios;
|
||||||
}
|
}
|
||||||
#define gpio_clear _gpio_clear
|
#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;
|
return (uint32_t)PORT_IN(gpioport) & gpios;
|
||||||
}
|
}
|
||||||
@ -158,4 +165,6 @@ static inline int platform_hwversion(void)
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void uart_pop(void);
|
||||||
#endif
|
#endif
|
||||||
|
@ -40,4 +40,3 @@ jtagtap_next(const uint8_t dTMS, const uint8_t dTDI)
|
|||||||
|
|
||||||
return ret != 0;
|
return ret != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,26 +21,105 @@
|
|||||||
#include "general.h"
|
#include "general.h"
|
||||||
#include "cdcacm.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/nvic.h>
|
||||||
|
#include <libopencm3/cm3/scb.h>
|
||||||
#include <libopencm3/cm3/scs.h>
|
#include <libopencm3/cm3/scs.h>
|
||||||
|
#include <libopencm3/cm3/systick.h>
|
||||||
|
|
||||||
#include <libopencm3/usb/usbd.h>
|
#include <libopencm3/usb/usbd.h>
|
||||||
#include <libopencm3/usb/cdc.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)
|
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)
|
void usbuart_set_line_coding(struct usb_cdc_line_coding *coding)
|
||||||
{
|
{
|
||||||
|
/* Not supported yet, only 115200 8bits/etc */
|
||||||
(void) coding;
|
(void) coding;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbuart_usb_out_cb(usbd_device *dev, uint8_t ep)
|
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)
|
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;
|
(void) ep;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/************************** UART Interrupt Handlers *************************/
|
||||||
* Read a character from the UART RX and stuff it in a software FIFO.
|
static void uart_rx_irq(void)
|
||||||
* Allowed to read from FIFO out pointer, but not write to it.
|
|
||||||
* Allowed to write to FIFO in pointer.
|
|
||||||
*/
|
|
||||||
void USBUART_ISR(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();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user