Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

USB CDC ZLP handling #116

Closed
28 changes: 23 additions & 5 deletions cores/arduino/USB/CDC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,15 @@ void Serial_::end(void)

void Serial_::accept(void)
{
uint8_t buffer[CDC_SERIAL_BUFFER_SIZE];
uint32_t len = usb.recv(CDC_ENDPOINT_OUT, &buffer, CDC_SERIAL_BUFFER_SIZE);
uint32_t ringBufferSpace = availableForStore();
if (ringBufferSpace < EPX_SIZE) {
// usb.recv will always try to receive up to EPX_SIZE bytes on the endpoint
// make sure there is enough space, so that data is not lost
return;
}

uint8_t buffer[EPX_SIZE];
uint32_t len = usb.recv(CDC_ENDPOINT_OUT, &buffer, sizeof(buffer));

uint8_t enableInterrupts = ((__get_PRIMASK() & 0x1) == 0);
__disable_irq();
Expand Down Expand Up @@ -197,7 +204,8 @@ int Serial_::available(void)
return CDC_SERIAL_BUFFER_SIZE;
}
if (buffer->head == buffer->tail) {
USB->DEVICE.DeviceEndpoint[CDC_ENDPOINT_OUT].EPINTENSET.reg = USB_DEVICE_EPINTENCLR_TRCPT(1);
if (usb.available(CDC_ENDPOINT_OUT))
accept();
}
return (uint32_t)(CDC_SERIAL_BUFFER_SIZE + buffer->head - buffer->tail) % CDC_SERIAL_BUFFER_SIZE;
}
Expand Down Expand Up @@ -236,8 +244,7 @@ int Serial_::read(void)
unsigned char c = buffer->buffer[buffer->tail];
buffer->tail = (uint32_t)(buffer->tail + 1) % CDC_SERIAL_BUFFER_SIZE;
buffer->full = false;
// if (usb.available(CDC_ENDPOINT_OUT))
// accept();

return c;
}
}
Expand Down Expand Up @@ -345,6 +352,17 @@ bool Serial_::rts() {
return _usbLineInfo.lineState & 0x2;
}

int Serial_::availableForStore(void) {
ring_buffer *buffer = &cdc_rx_buffer;

if (buffer->full)
return 0;
else if (buffer->head >= buffer->tail)
return CDC_SERIAL_BUFFER_SIZE - 1 - buffer->head + buffer->tail;
else
return buffer->tail - buffer->head - 1;
}

Serial_ SerialUSB(USBDevice);

#endif
2 changes: 2 additions & 0 deletions cores/arduino/USB/USBAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ class Serial_ : public Stream
};

private:
int availableForStore(void);

USBDeviceClass &usb;
RingBuffer *_cdc_rx_buffer;
};
Expand Down
26 changes: 19 additions & 7 deletions cores/arduino/USB/USBCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,12 +245,25 @@ void USBDeviceClass::handleEndpoint(uint8_t ep)
#if defined(CDC_ENABLED)
if (ep == CDC_ENDPOINT_OUT)
{
// The RAM Buffer is empty: we can receive data
//usbd.epBank0ResetReady(CDC_ENDPOINT_OUT);

// Handle received bytes
if (available(CDC_ENDPOINT_OUT))
{
// always disable transfer complete,
// in case the CDC receive buffer is full
usbd.epBank0DisableTransferComplete(CDC_ENDPOINT_OUT);

SerialUSB.accept();
}
else
{
// ZLP received

// The RAM Buffer is empty: we can receive data
usbd.epBank0ResetReady(CDC_ENDPOINT_OUT);

// Clear Transfer complete 0 flag
usbd.epBank0AckTransferComplete(CDC_ENDPOINT_OUT);
}
}
if (ep == CDC_ENDPOINT_IN)
{
Expand Down Expand Up @@ -434,10 +447,6 @@ void USBDeviceClass::initEP(uint32_t ep, uint32_t config)
}
else if (config == USB_ENDPOINT_TYPE_CONTROL)
{
// XXX: Needed?
// usbd.epBank0DisableAutoZLP(ep);
// usbd.epBank1DisableAutoZLP(ep);

// Setup Control OUT
usbd.epBank0SetSize(ep, 64);
usbd.epBank0SetAddress(ep, &udd_ep_out_cache_buffer[ep]);
Expand Down Expand Up @@ -535,6 +544,9 @@ uint32_t USBDeviceClass::recv(uint32_t ep, void *_data, uint32_t len)

// Clear Transfer complete 0 flag
usbd.epBank0AckTransferComplete(ep);

// Enable Transfer complete 0 interrupt
usbd.epBank0EnableTransferComplete(ep);
}

return len;
Expand Down