diff --git a/.gitignore b/.gitignore index a40d44d5..7f80f700 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,4 @@ tags *.b#* blackmagic_upgrade *.exe - +.DS_Store diff --git a/libopencm3 b/libopencm3 index 16df5b57..a6405c6f 160000 --- a/libopencm3 +++ b/libopencm3 @@ -1 +1 @@ -Subproject commit 16df5b57b8f7d80e7344188ba1a8484930a32afe +Subproject commit a6405c6f2a3383173ad5da40ea167e206d950ad1 diff --git a/src/main.c b/src/main.c index de119536..fe520d8e 100644 --- a/src/main.c +++ b/src/main.c @@ -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"); diff --git a/src/platforms/jeff/platform.c b/src/platforms/jeff/platform.c index 986c22a4..0873c9c8 100644 --- a/src/platforms/jeff/platform.c +++ b/src/platforms/jeff/platform.c @@ -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(); } diff --git a/src/platforms/jeff/platform.h b/src/platforms/jeff/platform.h index 8a8a7016..d205cb03 100644 --- a/src/platforms/jeff/platform.h +++ b/src/platforms/jeff/platform.h @@ -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 diff --git a/src/platforms/samd/jtagtap.c b/src/platforms/samd/jtagtap.c index 056a4fdb..07d67aeb 100644 --- a/src/platforms/samd/jtagtap.c +++ b/src/platforms/samd/jtagtap.c @@ -40,4 +40,3 @@ jtagtap_next(const uint8_t dTMS, const uint8_t dTDI) return ret != 0; } - diff --git a/src/platforms/samd/usbuart.c b/src/platforms/samd/usbuart.c index ceaef1b7..b7bd078b 100644 --- a/src/platforms/samd/usbuart.c +++ b/src/platforms/samd/usbuart.c @@ -21,26 +21,105 @@ #include "general.h" #include "cdcacm.h" +#include +#include +#include +#include +#include +#include + +#include #include +#include #include +#include + #include #include +#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(); }