aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2018-09-28 21:09:19 -0400
committerKevin O'Connor <kevin@koconnor.net>2018-09-30 22:55:21 -0400
commitd05aa81927af8672656b0b3f0ccdefb6e6b42f94 (patch)
tree8cf4bee789e68ad03e2b370073f1319b2aa17f1a
parentc0311bee338a433295a56241f29c1acbf52f0930 (diff)
downloadkutter-d05aa81927af8672656b0b3f0ccdefb6e6b42f94.tar.gz
kutter-d05aa81927af8672656b0b3f0ccdefb6e6b42f94.tar.xz
kutter-d05aa81927af8672656b0b3f0ccdefb6e6b42f94.zip
avr: Use generic usb_cdc code for usb serial support
Use the generic usb_cdc driver code instead of the "pjrc" usb driver code. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
-rw-r--r--config/generic-printrboard.cfg2
-rw-r--r--src/avr/Makefile4
-rw-r--r--src/avr/usbserial.c267
3 files changed, 226 insertions, 47 deletions
diff --git a/config/generic-printrboard.cfg b/config/generic-printrboard.cfg
index 5fd99e1e..8a667370 100644
--- a/config/generic-printrboard.cfg
+++ b/config/generic-printrboard.cfg
@@ -66,7 +66,7 @@ max_temp: 130
pin: PC6
[mcu]
-serial: /dev/ttyACM0
+serial: /dev/serial/by-id/usb-Klipper_Klipper_firmware_12345-if00
[printer]
kinematics: cartesian
diff --git a/src/avr/Makefile b/src/avr/Makefile
index 9f814a44..c3f3ab34 100644
--- a/src/avr/Makefile
+++ b/src/avr/Makefile
@@ -3,14 +3,14 @@
# Use the avr toolchain
CROSS_PREFIX=avr-
-dirs-y += src/avr src/generic lib/pjrc_usb_serial
+dirs-y += src/avr src/generic
CFLAGS += -mmcu=$(CONFIG_MCU)
# Add avr source files
src-y += avr/main.c avr/timer.c avr/gpio.c
src-$(CONFIG_AVR_WATCHDOG) += avr/watchdog.c
-src-$(CONFIG_AVR_USBSERIAL) += avr/usbserial.c ../lib/pjrc_usb_serial/usb_serial.c
+src-$(CONFIG_AVR_USBSERIAL) += avr/usbserial.c generic/usb_cdc.c
src-$(CONFIG_AVR_SERIAL) += avr/serial.c generic/serial_irq.c
# Suppress broken "misspelled signal handler" warnings on gcc 4.8.1
diff --git a/src/avr/usbserial.c b/src/avr/usbserial.c
index 2a16160d..188a1b14 100644
--- a/src/avr/usbserial.c
+++ b/src/avr/usbserial.c
@@ -1,71 +1,250 @@
-// Wrappers for AVR usb serial.
+// Hardware interface to USB on AVR at90usb
//
-// Copyright (C) 2016,2017 Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2018 Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU GPLv3 license.
-#include <string.h> // memmove
-#include "../lib/pjrc_usb_serial/usb_serial.h"
-#include "board/misc.h" // console_sendf
-#include "command.h" // command_find_and_dispatch
+#include <avr/interrupt.h> // USB_COM_vect
+#include <string.h> // NULL
+#include "autoconf.h" // CONFIG_MACH_at90usb1286
+#include "board/usb_cdc.h" // usb_notify_ep0
+#include "board/usb_cdc_ep.h" // USB_CDC_EP_BULK_IN
+#include "pgm.h" // READP
#include "sched.h" // DECL_INIT
-static uint8_t receive_buf[MESSAGE_MAX], receive_pos;
+// EPCFG0X definitions
+#define EP_TYPE_CONTROL 0x00
+#define EP_TYPE_BULK_IN 0x81
+#define EP_TYPE_BULK_OUT 0x80
+#define EP_TYPE_INTERRUPT_IN 0xC1
-void
-usbserial_init(void)
+// EPCFG1X definitions
+#define EP_SINGLE_BUFFER 0x02
+#define EP_DOUBLE_BUFFER 0x06
+#define EP_SIZE(s) ((s)==64 ? 0x30 : ((s)==32 ? 0x20 : ((s)==16 ? 0x10 : 0x00)))
+
+static void
+usb_write_packet(const uint8_t *data, uint8_t len)
{
- usb_init();
+ while (len--)
+ UEDATX = *data++;
}
-DECL_INIT(usbserial_init);
-// Check for new incoming data
static void
-console_check_input(void)
+usb_write_packet_progmem(const uint8_t *data, uint8_t len)
{
- for (;;) {
- if (receive_pos >= sizeof(receive_buf))
- break;
- int16_t ret = usb_serial_getchar();
- if (ret == -1)
- break;
- receive_buf[receive_pos++] = ret;
- }
+ while (len--)
+ UEDATX = READP(*data++);
}
-// Remove from the receive buffer the given number of bytes
static void
-console_pop_input(uint8_t len)
+usb_read_packet(uint8_t *data, uint8_t len)
+{
+ while (len--)
+ *data++ = UEDATX;
+}
+
+int_fast8_t
+usb_read_bulk_out(void *data, uint_fast8_t max_len)
+{
+ UENUM = USB_CDC_EP_BULK_OUT;
+ if (!(UEINTX & (1<<RWAL)))
+ // No data ready
+ return -1;
+ uint8_t len = UEBCLX;
+ usb_read_packet(data, len);
+ UEINTX = (uint8_t)~(1<<FIFOCON);
+ return len;
+}
+
+int_fast8_t
+usb_send_bulk_in(void *data, uint_fast8_t len)
+{
+ UENUM = USB_CDC_EP_BULK_IN;
+ if (!(UEINTX & (1<<RWAL)))
+ // Buffer full
+ return -1;
+ usb_write_packet(data, len);
+ UEINTX = (uint8_t)~((1<<FIFOCON) | (1<<RXOUTI));
+ return len;
+}
+
+int_fast8_t
+usb_read_ep0(void *data, uint_fast8_t max_len)
{
- uint8_t needcopy = receive_pos - len;
- if (needcopy) {
- memmove(receive_buf, &receive_buf[len], needcopy);
- sched_wake_tasks();
+ UENUM = 0;
+ uint8_t ueintx = UEINTX;
+ if (ueintx & (1<<RXSTPI))
+ return -2;
+ if (!(ueintx & (1<<RXOUTI))) {
+ // Not ready to receive data
+ UEIENX = (1<<RXSTPE) | (1<<RXOUTE);
+ return -1;
}
- receive_pos = needcopy;
+ usb_read_packet(data, max_len);
+ if (UEINTX & (1<<RXSTPI))
+ return -2;
+ UEINTX = ~(1<<RXOUTI);
+ return max_len;
+}
+
+int_fast8_t
+usb_read_ep0_setup(void *data, uint_fast8_t max_len)
+{
+ UENUM = 0;
+ uint8_t ueintx = UEINTX;
+ if (!(ueintx & ((1<<RXSTPI)))) {
+ // No data ready to read
+ UEIENX = 1<<RXSTPE;
+ return -1;
+ }
+ usb_read_packet(data, max_len);
+ UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI));
+ return max_len;
+}
+
+static int8_t
+_usb_send_ep0(const void *data, uint8_t len, uint8_t progmem)
+{
+ UENUM = 0;
+ uint8_t ueintx = UEINTX;
+ if (ueintx & ((1<<RXSTPI) | (1<<RXOUTI)))
+ return -2;
+ if (!(ueintx & (1<<TXINI))) {
+ // Not ready to send
+ UEIENX = (1<<RXSTPE) | (1<<RXOUTE) | (1<<TXINE);
+ return -1;
+ }
+ if (progmem)
+ usb_write_packet_progmem(data, len);
+ else
+ usb_write_packet(data, len);
+ UEINTX = ~(1<<TXINI);
+ return len;
+}
+
+int_fast8_t
+usb_send_ep0(const void *data, uint_fast8_t len)
+{
+ return _usb_send_ep0(data, len, 0);
+}
+
+int_fast8_t
+usb_send_ep0_progmem(const void *data, uint_fast8_t len)
+{
+ return _usb_send_ep0(data, len, 1);
}
-// Process any incoming commands
void
-console_task(void)
+usb_stall_ep0(void)
{
- console_check_input();
- uint_fast8_t pop_count;
- int8_t ret = command_find_and_dispatch(receive_buf, receive_pos, &pop_count);
- if (ret)
- console_pop_input(pop_count);
+ UENUM = 0;
+ UECONX = (1<<STALLRQ) | (1<<EPEN);
+ UEIENX = 1<<RXSTPE;
}
-DECL_TASK(console_task);
-// Encode and transmit a "response" message
+static uint8_t set_address;
+
void
-console_sendf(const struct command_encoder *ce, va_list args)
+usb_set_address(uint_fast8_t addr)
{
- // Generate message
- static uint8_t buf[MESSAGE_MAX];
- uint8_t msglen = command_encode_and_frame(buf, ce, args);
+ set_address = addr | (1<<ADDEN);
+ _usb_send_ep0(NULL, 0, 0);
+ UEIENX = (1<<RXSTPE) | (1<<TXINE);
+}
+
+void
+usb_set_configure(void)
+{
+ UENUM = USB_CDC_EP_ACM;
+ UECONX = 1<<EPEN;
+ UECFG0X = EP_TYPE_INTERRUPT_IN;
+ UECFG1X = EP_SIZE(USB_CDC_EP_ACM_SIZE) | EP_SINGLE_BUFFER;
- // Transmit message
- usb_serial_write((void*)buf, msglen);
- usb_serial_flush_output();
+ UENUM = USB_CDC_EP_BULK_OUT;
+ UECONX = 1<<EPEN;
+ UECFG0X = EP_TYPE_BULK_OUT;
+ UECFG1X = EP_SIZE(USB_CDC_EP_BULK_OUT_SIZE) | EP_DOUBLE_BUFFER;
+ UEIENX = 1<<RXOUTE;
+
+ UENUM = USB_CDC_EP_BULK_IN;
+ UECONX = 1<<EPEN;
+ UECFG0X = EP_TYPE_BULK_IN;
+ UECFG1X = EP_SIZE(USB_CDC_EP_BULK_IN_SIZE) | EP_DOUBLE_BUFFER;
+ UEIENX = 1<<TXINE;
+}
+
+void
+usbserial_init(void)
+{
+ // Set USB controller to device mode
+ UHWCON = (1<<UIMOD) | (1<<UVREGE);
+
+ // Enable USB clock
+ USBCON = (1<<USBE) | (1<<FRZCLK);
+ if (CONFIG_MACH_at90usb1286)
+ PLLCSR = (1<<PLLP2) | (1<<PLLP0) | (1<<PLLE);
+ else
+ PLLCSR = (1<<PLLP2) | (1<<PLLP1) | (1<<PLLE);
+ while (!(PLLCSR & (1<<PLOCK)))
+ ;
+ USBCON = (1<<USBE) | (1<<OTGPADE);
+
+ // Enable USB pullup
+ UDCON = 0;
+
+ // Enable interrupts
+ UDIEN = 1<<EORSTE;
+}
+DECL_INIT(usbserial_init);
+
+ISR(USB_GEN_vect)
+{
+ uint8_t udint = UDINT;
+ UDINT = 0;
+ if (udint & (1<<EORSTI)) {
+ // Configure endpoint 0 after usb reset completes
+ uint8_t old_uenum = UENUM;
+ UENUM = 0;
+ UECONX = 1<<EPEN;
+ UECFG0X = EP_TYPE_CONTROL;
+ UECFG1X = EP_SIZE(USB_CDC_EP0_SIZE) | EP_SINGLE_BUFFER;
+ UEIENX = 1<<RXSTPE;
+ UENUM = old_uenum;
+ }
+}
+
+ISR(USB_COM_vect)
+{
+ uint8_t ueint = UEINT, old_uenum = UENUM;
+ if (ueint & (1<<0)) {
+ UENUM = 0;
+ UEIENX = 0;
+ usb_notify_ep0();
+
+ uint8_t ueintx = UEINTX;
+ if (!(ueintx & (1<<RXSTPI)) && (ueintx & (1<<TXINI)) && set_address) {
+ // Ack from set_address command sent - now update address
+ UDADDR = set_address;
+ set_address = 0;
+ }
+ }
+ if (ueint & (1<<USB_CDC_EP_BULK_OUT)) {
+ UENUM = USB_CDC_EP_BULK_OUT;
+ UEINTX = ~(1<<RXOUTI);
+ usb_notify_bulk_out();
+ }
+ if (ueint & (1<<USB_CDC_EP_BULK_IN)) {
+ UENUM = USB_CDC_EP_BULK_IN;
+ UEINTX = ~((1<<RXOUTI) | (1<<TXINI));
+ usb_notify_bulk_in();
+ }
+ UENUM = old_uenum;
+}
+
+void
+usbserial_shutdown(void)
+{
+ UEIENX = 1<<RXSTPE;
}
+DECL_SHUTDOWN(usbserial_shutdown);