- CDC class OS-managed blocking buffer added; - some low-level USB function signatures have been changed
This commit is contained in:
parent
93a0ff53e6
commit
627e038dbb
43
class/cdc.c
43
class/cdc.c
@ -6,9 +6,16 @@
|
||||
|
||||
#include "../usb.h"
|
||||
|
||||
#include <blocking_io/blocking_fifo.h>
|
||||
|
||||
// state
|
||||
static USB_CdcState cdcs;
|
||||
static uint8_t cdc_buffer[USB_CDC_BUFSIZE];
|
||||
static USB_CdcState cdcs = { 0 };
|
||||
static uint8_t tx_buffer[USB_CDC_PCKT_BUFSIZE];
|
||||
|
||||
#define USB_CDC_FIFO_MEM_SIZE (2048)
|
||||
|
||||
static uint8_t fifo_mem[USB_CDC_FIFO_MEM_SIZE];
|
||||
static BFifo fifo;
|
||||
|
||||
void usb_cdc_init(const USB_CdcAssignments *as) {
|
||||
// clear the structure
|
||||
@ -24,10 +31,11 @@ void usb_cdc_init(const USB_CdcAssignments *as) {
|
||||
// fill-in assigments
|
||||
cdcs.ep_assignments = *as;
|
||||
|
||||
// assign buffer pointer
|
||||
USB_CdcBuffer * buf = &cdcs.buffer;
|
||||
buf->p = cdc_buffer;
|
||||
buf->size = USB_CDC_BUFSIZE;
|
||||
// initialize buffer
|
||||
bfifo_create(&fifo, fifo_mem, USB_CDC_FIFO_MEM_SIZE);
|
||||
|
||||
// from now on CDC is considered initialized
|
||||
cdcs.initialized = true;
|
||||
}
|
||||
|
||||
int usb_cdc_process_and_return(USB_CallbackEvent *cbevt) {
|
||||
@ -37,12 +45,12 @@ int usb_cdc_process_and_return(USB_CallbackEvent *cbevt) {
|
||||
switch (cbevt->setup_request->bRequest) {
|
||||
case USB_CDC_SET_LINE_CODING: // set line coding
|
||||
memcpy(&cdcs.line_coding, cbevt->data, sizeof(USB_Cdc_LineCodingStruct));
|
||||
MSG("%u\n", cdcs.line_coding.dwDTERate);
|
||||
//MSG("%u\n", cdcs.line_coding.dwDTERate);
|
||||
ret = 0;
|
||||
break;
|
||||
case USB_CDC_SET_CONTROL_LINE_STATE: // set control line state
|
||||
memcpy(&cdcs.control_line_state, cbevt->data, sizeof(USB_Cdc_ControlLineStateStruct));
|
||||
MSG("%u\n", cdcs.control_line_state.D);
|
||||
//MSG("%u\n", cdcs.control_line_state.D);
|
||||
ret = 0;
|
||||
break;
|
||||
default:
|
||||
@ -63,6 +71,7 @@ int usb_cdc_process_and_return(USB_CallbackEvent *cbevt) {
|
||||
if (cbevt->ep == cdcs.ep_assignments.data_ep) {
|
||||
//MSG("%c\n", cbevt->data[0]);
|
||||
ret = 0;
|
||||
|
||||
usbcore_write(cdcs.ep_assignments.data_ep, cbevt->data, cbevt->size); // echo
|
||||
}
|
||||
break;
|
||||
@ -75,7 +84,13 @@ int usb_cdc_process_and_return(USB_CallbackEvent *cbevt) {
|
||||
} else if (cbevt->ep == cdcs.ep_assignments.data_ep) { // if data are requested
|
||||
//usbcore_write(cdcs.ep_assignments.data_ep, NULL, 0); // send ZLP
|
||||
ret = 0;
|
||||
// TODO!!
|
||||
|
||||
// read from the fifo
|
||||
uint32_t readSize = bfifo_read(&fifo, tx_buffer, USB_CDC_PCKT_BUFSIZE);
|
||||
if (readSize > 0) {
|
||||
uint32_t writeSize = usbcore_write(cdcs.ep_assignments.data_ep, tx_buffer, readSize); // write data acquired from the buffer
|
||||
bfifo_pop(&fifo, writeSize, 0); // pop with no blocking
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,6 +101,12 @@ int usb_cdc_process_and_return(USB_CallbackEvent *cbevt) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
void usb_cdc_write(const uint8_t * data, uint32_t size) {
|
||||
|
||||
void usb_event_callback(USB_CallbackEvent *cbevt) {
|
||||
usb_cdc_process_and_return(cbevt);
|
||||
}
|
||||
|
||||
void usb_cdc_write(const uint8_t * data, uint32_t size) {
|
||||
if (cdcs.initialized) {
|
||||
bfifo_push_all(&fifo, data, size);
|
||||
}
|
||||
}
|
11
class/cdc.h
11
class/cdc.h
@ -46,17 +46,11 @@ typedef struct {
|
||||
uint8_t data_ep : 4; // data endpoint
|
||||
} USB_CdcAssignments;
|
||||
|
||||
typedef struct {
|
||||
uint32_t size;
|
||||
uint8_t * p;
|
||||
uint8_t read_idx, write_idx;
|
||||
} USB_CdcBuffer;
|
||||
|
||||
typedef struct {
|
||||
USB_CdcAssignments ep_assignments; // endpoint assignments
|
||||
USB_CdcBuffer buffer; // buffer
|
||||
USB_Cdc_LineCodingStruct line_coding; // line coding
|
||||
USB_Cdc_ControlLineStateStruct control_line_state; // control line state
|
||||
bool initialized; // CDC is initialized
|
||||
} USB_CdcState;
|
||||
|
||||
// ----------------
|
||||
@ -68,11 +62,12 @@ typedef struct {
|
||||
|
||||
// ----------------
|
||||
|
||||
#define USB_CDC_BUFSIZE (256)
|
||||
#define USB_CDC_PCKT_BUFSIZE (120)
|
||||
|
||||
// ----------------
|
||||
|
||||
void usb_cdc_init(const USB_CdcAssignments * as);
|
||||
int usb_cdc_process_and_return(USB_CallbackEvent * cbevt);
|
||||
void usb_cdc_write(const uint8_t * data, uint32_t size);
|
||||
|
||||
#endif /* CORE_USB_CLASS_CDC */
|
||||
|
4
usb.c
4
usb.c
@ -222,6 +222,6 @@ void usbcore_process_nonsetup_event(USBDRV_CallbackCompound *cbcpd) {
|
||||
}
|
||||
}
|
||||
|
||||
void usbcore_write(uint8_t ep, const uint8_t *data, uint16_t size) {
|
||||
usbdrv_arm_IN_endpoint(ep, data, size);
|
||||
uint32_t usbcore_write(uint8_t ep, const uint8_t *data, uint16_t size) {
|
||||
return usbdrv_arm_IN_endpoint(ep, data, size);
|
||||
}
|
2
usb.h
2
usb.h
@ -4,6 +4,6 @@
|
||||
#include "usb_callback_event.h"
|
||||
|
||||
void usbcore_init(); // initialize USB core
|
||||
void usbcore_write(uint8_t ep, const uint8_t *data, uint16_t size); // write data to endpoint
|
||||
uint32_t usbcore_write(uint8_t ep, const uint8_t *data, uint16_t size); // write data to endpoint, return with number of bytes actually written
|
||||
|
||||
#endif /* CORE_USB_USB */
|
||||
|
39
usb_driver.c
39
usb_driver.c
@ -82,6 +82,7 @@ void usbdrv_init() {
|
||||
usbdrv_initial_ep0_setup();
|
||||
usbdrv_power_and_connect(true);
|
||||
|
||||
NVIC_SetPriority(OTG_FS_IRQn, 6);
|
||||
NVIC_EnableIRQ(OTG_FS_IRQn);
|
||||
}
|
||||
|
||||
@ -471,27 +472,31 @@ void usbdrv_fetch_received_data(uint8_t ep, uint16_t len) {
|
||||
}
|
||||
|
||||
// write data to specific endpoint FIFO
|
||||
void usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len) {
|
||||
uint32_t usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len) {
|
||||
/*WRITE_FIELD(USBINEP[ep].DIEPTSIZ, USB_OTG_DIEPTSIZ_XFRSIZ, len);
|
||||
WRITE_FIELD(USBINEP[ep].DIEPTSIZ, USB_OTG_DIEPTSIZ_PKTCNT, 1);*/
|
||||
|
||||
// endpoint is already armed
|
||||
if (gs.ep_IN[ep].task_commenced == USB_EPEVT_ARMED) {
|
||||
return;
|
||||
}
|
||||
// if (gs.ep_IN[ep].task_commenced == USB_EPEVT_ARMED) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
gs.ep_IN[ep].task_commenced = USB_EPEVT_ARMED;
|
||||
// gs.ep_IN[ep].task_commenced = USB_EPEVT_ARMED;
|
||||
|
||||
// determine final write size
|
||||
uint32_t freeSize = USBINEP[ep].DTXFSTS * sizeof(uint32_t); // get free transmit buffer size
|
||||
uint16_t writeSize = MIN(freeSize, len); // limit transmit size to free size
|
||||
|
||||
// calculate packet count based on max packet size
|
||||
uint16_t mps = gs.ep_IN[ep].max_packet_size;
|
||||
uint16_t packet_count = 1; // for ZLPs
|
||||
if (len > 0) { // if length is nonzero
|
||||
packet_count = len / mps + (((len % mps) > 0) ? 1 : 0);
|
||||
if (writeSize > 0) { // if length is nonzero
|
||||
packet_count = writeSize / mps + (((writeSize % mps) > 0) ? 1 : 0);
|
||||
}
|
||||
// TODO: ZLP ending
|
||||
|
||||
// program DIEPTSIZ with transfer length (TODO: currently only a single transfer!)
|
||||
USBINEP[ep].DIEPTSIZ = (packet_count << USB_OTG_DIEPTSIZ_PKTCNT_Pos) | len;
|
||||
USBINEP[ep].DIEPTSIZ = (packet_count << USB_OTG_DIEPTSIZ_PKTCNT_Pos) | writeSize;
|
||||
|
||||
// enable endpoint and cancel responding NAK
|
||||
SET_BIT(USBINEP[ep].DIEPCTL, USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK);
|
||||
@ -501,7 +506,7 @@ void usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len) {
|
||||
|
||||
// push full dwords
|
||||
volatile uint32_t *p = (uint32_t *)USBFIFO(ep);
|
||||
uint32_t floorlen_dwords = len >> 2;
|
||||
uint32_t floorlen_dwords = writeSize >> 2;
|
||||
for (uint16_t i = 0; i < floorlen_dwords; i++) {
|
||||
uint16_t i0 = 4 * i;
|
||||
uint32_t dword = data[i0] | (data[i0 + 1] << 8) | (data[i0 + 2] << 16) | (data[i0 + 3] << 24);
|
||||
@ -521,6 +526,9 @@ void usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len) {
|
||||
|
||||
// unmask USB interrupts
|
||||
SET_BIT(USBG->GAHBCFG, USB_OTG_GAHBCFG_GINT);
|
||||
|
||||
// return with written size
|
||||
return writeSize;
|
||||
}
|
||||
|
||||
// arm OUT endpoint
|
||||
@ -607,13 +615,13 @@ void usbdrv_process_event(uint8_t evt_code, USBDRV_EventData *evt_data) {
|
||||
gs.state = USB_FSM_SETUP_OPERATE; // wait for speed negotiation
|
||||
}
|
||||
break;
|
||||
case USB_FSM_SETUP_OPERATE: { // expect SETUP transactions
|
||||
case USB_FSM_SETUP_OPERATE: { // expect SETUP transactions first, then everything else as well
|
||||
switch (evt_code) {
|
||||
case USB_EVT_RECEPTION_DONE: { // reception done
|
||||
|
||||
for (uint32_t i = 0; i < 100000; i++) {
|
||||
__NOP();
|
||||
}
|
||||
// for (uint32_t i = 0; i < 100000; i++) {
|
||||
// __NOP();
|
||||
// }
|
||||
|
||||
USBDRV_EventData evt_data = {0};
|
||||
usbdrv_process_rx_fifo_top(&evt_data); // process rx fifo top
|
||||
@ -646,7 +654,7 @@ void usbdrv_process_event(uint8_t evt_code, USBDRV_EventData *evt_data) {
|
||||
usbcore_process_setup_pckt(gs.rx_buf, gs.rx_buf_level, stage);
|
||||
}
|
||||
|
||||
//SET_BIT(USBG->GINTMSK, USB_OTG_GINTMSK_RXFLVLM); // unmask interrupt
|
||||
// SET_BIT(USBG->GINTMSK, USB_OTG_GINTMSK_RXFLVLM); // unmask interrupt
|
||||
} else { // not EP0
|
||||
if (evt_data.rx.pckt_status == USB_PCKT_STATUS_OUT_DATA_RECV) { // TODO maybe the
|
||||
USBDRV_CallbackCompound cbcpd;
|
||||
@ -682,6 +690,7 @@ void usbdrv_process_event(uint8_t evt_code, USBDRV_EventData *evt_data) {
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case USB_EVT_IN_DONE: { // some IN operations have finished
|
||||
@ -804,7 +813,7 @@ void OTG_FS_IRQHandler() {
|
||||
if (ints & USB_OTG_GINTSTS_RXFLVL) {
|
||||
// SET_BIT(USBG->GINTSTS, USB_OTG_GINTSTS_RXFLVL); // clear interrupt
|
||||
USBMSG("RX DONE\n");
|
||||
//CLEAR_BIT(USBG->GINTMSK, USB_OTG_GINTMSK_RXFLVLM); // mask interrupt until processing is done
|
||||
// CLEAR_BIT(USBG->GINTMSK, USB_OTG_GINTMSK_RXFLVLM); // mask interrupt until processing is done
|
||||
usbdrv_process_event(USB_EVT_RECEPTION_DONE, NULL); // process event
|
||||
// usbdrv_push_event(USB_EVT_RECEPTION_DONE, NULL); // push event
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ void usbdrv_set_rx_fifo_size(uint16_t size); // set Rx FIFO size
|
||||
void usbdrv_fetch_received_data(uint8_t ep, uint16_t len); // fetch received data from RX FIFO to receive buffer
|
||||
void usbdrv_process_rx_fifo_top(USBDRV_EventData *evt_data); // see what's on top of Rx FIFO
|
||||
|
||||
void usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len); // write data to specific endpoint FIFO
|
||||
uint32_t usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len); // write data to specific endpoint FIFO
|
||||
#define USBDRV_ARM_IN_ZLP(ep) usbdrv_arm_IN_endpoint((ep), NULL, 0)
|
||||
void usbdrv_arm_OUT_endpoint(uint8_t ep, uint8_t size); // arm OUT endpoint
|
||||
bool usbdrv_get_endpoint_interrupt_flag(uint8_t ep, uint8_t dir); // get endpoint interrupt flag
|
||||
|
Loading…
x
Reference in New Issue
Block a user