Browse Source

Add USB Serial flush

teensy4-core
PaulStoffregen 5 years ago
parent
commit
b062b68308
3 changed files with 63 additions and 36 deletions
  1. +9
    -1
      teensy4/usb.c
  2. +3
    -0
      teensy4/usb_dev.h
  3. +51
    -35
      teensy4/usb_serial.c

+ 9
- 1
teensy4/usb.c View File

static uint8_t endpoint0_buffer[8]; static uint8_t endpoint0_buffer[8];
static uint8_t usb_reboot_timer = 0; static uint8_t usb_reboot_timer = 0;


void (*usb_timer0_callback)(void) = NULL;
void (*usb_timer1_callback)(void) = NULL;


static void isr(void); static void isr(void);
static void endpoint0_setup(uint64_t setupdata); static void endpoint0_setup(uint64_t setupdata);
//printf("shut off USB\n"); //printf("shut off USB\n");
//} //}
} }
if (status & USB_USBSTS_TI0) {
if (usb_timer0_callback != NULL) usb_timer0_callback();
}
if (status & USB_USBSTS_TI1) {
if (usb_timer1_callback != NULL) usb_timer1_callback();
}
if (status & USB_USBSTS_PCI) { if (status & USB_USBSTS_PCI) {
if (USB1_PORTSC1 & USB_PORTSC1_HSP) { if (USB1_PORTSC1 & USB_PORTSC1_HSP) {
//printf("port at 480 Mbit\n"); //printf("port at 480 Mbit\n");
{ {
transfer_t *t, *next; transfer_t *t, *next;


printf("run_callbacks\n");
//printf("run_callbacks\n");
t = ep->first_transfer; t = ep->first_transfer;
while (t && (uint32_t)t != 1) { while (t && (uint32_t)t != 1) {
if (!(t->status & (1<<7))) { if (!(t->status & (1<<7))) {

+ 3
- 0
teensy4/usb_dev.h View File

void usb_receive(int endpoint_number, transfer_t *transfer); void usb_receive(int endpoint_number, transfer_t *transfer);
uint32_t usb_transfer_status(const transfer_t *transfer); uint32_t usb_transfer_status(const transfer_t *transfer);


extern void (*usb_timer0_callback)(void);
extern void (*usb_timer1_callback)(void);




+ 51
- 35
teensy4/usb_serial.c View File

//static usb_packet_t *tx_packet=NULL; //static usb_packet_t *tx_packet=NULL;
static volatile uint8_t tx_noautoflush=0; static volatile uint8_t tx_noautoflush=0;


#define TRANSMIT_FLUSH_TIMEOUT 5 /* in milliseconds */
// TODO: should be 2 different timeouts, high speed (480) vs full speed (12)
#define TRANSMIT_FLUSH_TIMEOUT 75 /* in microseconds */


static void timer_config(void (*callback)(void), uint32_t microseconds);
static void timer_start_oneshot();
static void timer_stop();
static void usb_serial_flush_callback(void);




#define RX_NUM 3 #define RX_NUM 3
{ {
int len = CDC_RX_SIZE - ((t->status >> 16) & 0x7FFF); int len = CDC_RX_SIZE - ((t->status >> 16) & 0x7FFF);
int index = t->callback_param; int index = t->callback_param;
printf("rx event, len=%d, i=%d\n", len, index);
//printf("rx event, len=%d, i=%d\n", len, index);
rx_count[index] = len; rx_count[index] = len;
rx_index[index] = 0; rx_index[index] = 0;
} }
usb_config_tx(CDC_TX_ENDPOINT, CDC_TX_SIZE, 0, NULL); usb_config_tx(CDC_TX_ENDPOINT, CDC_TX_SIZE, 0, NULL);
usb_prepare_transfer(rx_transfer + 0, rx_buffer + 0, CDC_RX_SIZE, 0); usb_prepare_transfer(rx_transfer + 0, rx_buffer + 0, CDC_RX_SIZE, 0);
usb_receive(CDC_RX_ENDPOINT, rx_transfer + 0); usb_receive(CDC_RX_ENDPOINT, rx_transfer + 0);
timer_config(usb_serial_flush_callback, TRANSMIT_FLUSH_TIMEOUT);
} }






extern volatile uint32_t systick_millis_count; extern volatile uint32_t systick_millis_count;


static void timer_config(void (*callback)(void), uint32_t microseconds);
static void timer_start_oneshot();
static void timer_stop();

static void timer_config(void (*callback)(void), uint32_t microseconds)
{
usb_timer0_callback = callback;
USB1_GPTIMER0CTRL = 0;
USB1_GPTIMER0LD = microseconds - 1;
USB1_USBINTR |= USB_USBINTR_TIE0;
}

static void timer_start_oneshot(void)
{
// restarts timer if already running (retriggerable one-shot)
USB1_GPTIMER0CTRL = USB_GPTIMERCTRL_GPTRUN | USB_GPTIMERCTRL_GPTRST;
}

static void timer_stop(void)
{
USB1_GPTIMER0CTRL = 0;
}


int usb_serial_write(const void *buffer, uint32_t size) int usb_serial_write(const void *buffer, uint32_t size)
{ {
uint32_t sent=0; uint32_t sent=0;
if (!usb_configuration) return 0; if (!usb_configuration) return 0;
while (size > 0) { while (size > 0) {
transfer_t *xfer = tx_transfer + tx_head; transfer_t *xfer = tx_transfer + tx_head;
int waiting=0;
uint32_t wait_begin_at=0;
//int waiting=0;
//uint32_t wait_begin_at=0;
while (!tx_available) { while (!tx_available) {
//digitalWriteFast(3, HIGH); //digitalWriteFast(3, HIGH);
uint32_t status = usb_transfer_status(xfer); uint32_t status = usb_transfer_status(xfer);
sent += tx_available; sent += tx_available;
data += tx_available; data += tx_available;
tx_available = 0; tx_available = 0;
timer_stop();
} else { } else {
memcpy(txdata, data, size); memcpy(txdata, data, size);
tx_available -= size; tx_available -= size;
sent += size; sent += size;
size = 0; size = 0;
timer_start_oneshot();
} }
} }
return sent; return sent;


void usb_serial_flush_output(void) void usb_serial_flush_output(void)
{ {
#if 0
if (!usb_configuration) return; if (!usb_configuration) return;
if (tx_available == 0) return;
tx_noautoflush = 1; tx_noautoflush = 1;
if (tx_packet) {
usb_cdc_transmit_flush_timer = 0;
tx_packet->len = tx_packet->index;
usb_tx(CDC_TX_ENDPOINT, tx_packet);
tx_packet = NULL;
} else {
usb_packet_t *tx = usb_malloc();
if (tx) {
usb_cdc_transmit_flush_timer = 0;
usb_tx(CDC_TX_ENDPOINT, tx);
} else {
usb_cdc_transmit_flush_timer = 1;
}
}
transfer_t *xfer = tx_transfer + tx_head;
usb_prepare_transfer(xfer, txbuffer + (tx_head * TX_SIZE), TX_SIZE - tx_available, 0);
usb_transmit(CDC_TX_ENDPOINT, xfer);
if (++tx_head >= TX_NUM) tx_head = 0;
tx_available = 0;
tx_noautoflush = 0; tx_noautoflush = 0;
#endif
} }


void usb_serial_flush_callback(void)
static void usb_serial_flush_callback(void)
{ {
#if 0
if (tx_noautoflush) return; if (tx_noautoflush) return;
if (tx_packet) {
tx_packet->len = tx_packet->index;
usb_tx(CDC_TX_ENDPOINT, tx_packet);
tx_packet = NULL;
} else {
usb_packet_t *tx = usb_malloc();
if (tx) {
usb_tx(CDC_TX_ENDPOINT, tx);
} else {
usb_cdc_transmit_flush_timer = 1;
}
}
#endif
if (!usb_configuration) return;
if (tx_available == 0) return;
//printf("flush callback, %d bytes\n", TX_SIZE - tx_available);
transfer_t *xfer = tx_transfer + tx_head;
usb_prepare_transfer(xfer, txbuffer + (tx_head * TX_SIZE), TX_SIZE - tx_available, 0);
usb_transmit(CDC_TX_ENDPOINT, xfer);
if (++tx_head >= TX_NUM) tx_head = 0;
tx_available = 0;
} }





Loading…
Cancel
Save