Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/soc/app/dcd_tntusb.c b/soc/app/dcd_tntusb.c
- index f91174e..5b62d83 100644
- --- a/soc/app/dcd_tntusb.c
- +++ b/soc/app/dcd_tntusb.c
- @@ -11,10 +11,18 @@
- #define USB_CHECK(x) do { if (!(x)) printf("USB: check fail: " #x " (%s:%d)\n", __FILE__, __LINE__); } while (0)
- typedef struct {
- - int mem_free_ptr_in;
- - int mem_free_ptr_out;
- - int ep_mps[16];
- - int ep_in_xfer_len[16];
- + uint8_t *buf;
- + uint16_t len; /* Total transfer length */
- + uint16_t ofs; /* Offset in the total transfer */
- + uint16_t plen; /* Length of last queued packet */
- + uint16_t mps; /* Max Packet Size */
- +} g_tntusb_xfer_t;
- +
- +typedef struct {
- + uint16_t mem_free_ptr_in;
- + uint16_t mem_free_ptr_out;
- + bool ep0_stall;
- + g_tntusb_xfer_t xfer[16][2];
- } g_tntusb_t;
- static g_tntusb_t g_usb;
- @@ -22,7 +30,7 @@ static g_tntusb_t g_usb;
- static void _usb_data_write(unsigned int dst_ofs, const void *src, int len) {
- /* FIXME unaligned ofs */
- const uint32_t *src_u32 = src;
- - volatile uint32_t *dst_u32 = (volatile uint32_t *)((USB_CORE_OFFSET+USB_TXMEM) + dst_ofs);
- + volatile uint32_t *dst_u32 = (volatile uint32_t *)((USB_DATA_BASE) + dst_ofs);
- len = (len + 3) >> 2;
- while (len--)
- @@ -31,7 +39,7 @@ static void _usb_data_write(unsigned int dst_ofs, const void *src, int len) {
- static void _usb_data_read (void *dst, unsigned int src_ofs, int len) {
- /* FIXME unaligned ofs */
- - volatile uint32_t *src_u32 = (volatile uint32_t *)((USB_CORE_OFFSET+USB_RXMEM) + src_ofs);
- + volatile uint32_t *src_u32 = (volatile uint32_t *)((USB_DATA_BASE) + src_ofs);
- uint32_t *dst_u32 = dst;
- int i = len >> 2;
- @@ -125,11 +133,137 @@ void dcd_remote_wakeup(uint8_t rhport)
- /* DCD Endpoint port
- *------------------------------------------------------------------*/
- +static bool
- +_ep_advance_xfer_in(const uint8_t epnum)
- +{
- + g_tntusb_xfer_t *xf = &g_usb.xfer[epnum][TUSB_DIR_IN];
- + uint32_t bds = tntusb_ep_regs[epnum].in.bd[0].csr;
- + bool pkt_done = false;
- + int len;
- +
- + /* Handle EP0 stalls */
- + if ((epnum == 0) && g_usb.ep0_stall) {
- + if ((bds & TNTUSB_BD_STATE_MSK) != TNTUSB_BD_STATE_RDY_STALL)
- + tntusb_ep_regs[epnum].in.bd[0].csr = TNTUSB_BD_STATE_RDY_STALL;
- + return false;
- + }
- +
- + /* Just retry on errors */
- + if ((bds & TNTUSB_BD_STATE_MSK) == TNTUSB_BD_STATE_DONE_ERR) {
- + tntusb_ep_regs[epnum].in.bd[0].csr = TNTUSB_BD_STATE_RDY_DATA | TNTUSB_BD_LEN(xf->plen);
- + return true;
- + }
- +
- + /* Packet done ? */
- + if ((bds & TNTUSB_BD_STATE_MSK) == TNTUSB_BD_STATE_DONE_OK)
- + {
- + tntusb_ep_regs[epnum].in.bd[0].csr = 0;
- + xf->ofs += xf->plen;
- +
- + if ((xf->ofs == xf->len) && (((xf->len % xf->mps) != 0) || ~xf->plen))
- + {
- + len = xf->len;
- +
- + xf->buf = NULL;
- + xf->len = 0;
- + xf->ofs = 0;
- + xf->plen = 0;
- +
- + dcd_event_xfer_complete(0, epnum | 0x80, len, XFER_RESULT_SUCCESS, true);
- + }
- + pkt_done = true;
- + }
- +
- + /* Need to submit another one */
- + if (pkt_done || ((bds & TNTUSB_BD_STATE_MSK) == TNTUSB_BD_STATE_NONE))
- + {
- + if (xf->buf) {
- + /* Select packet size */
- + xf->plen = xf->len - xf->ofs;
- + if (xf->plen > xf->mps)
- + xf->plen = xf->mps;
- +
- + /* Fill data buffer */
- + _usb_data_write(tntusb_ep_regs[epnum].in.bd[0].ptr, &xf->buf[xf->ofs], xf->plen);
- +
- + /* Submit packet */
- + tntusb_ep_regs[epnum].in.bd[0].csr = TNTUSB_BD_STATE_RDY_DATA | TNTUSB_BD_LEN(xf->plen);
- + }
- +
- + return true;
- + }
- +
- + return pkt_done;
- +}
- +
- +static bool
- +_ep_advance_xfer_out(const uint8_t epnum)
- +{
- + g_tntusb_xfer_t *xf = &g_usb.xfer[epnum][TUSB_DIR_OUT];
- + uint32_t bds = tntusb_ep_regs[epnum].out.bd[0].csr;
- + bool pkt_done = false;
- + int len;
- +
- + /* Handle EP0 stalls */
- + if ((epnum == 0) && g_usb.ep0_stall) {
- + if ((bds & TNTUSB_BD_STATE_MSK) != TNTUSB_BD_STATE_RDY_STALL)
- + tntusb_ep_regs[epnum].out.bd[0].csr = TNTUSB_BD_STATE_RDY_STALL;
- + return false;
- + }
- +
- + /* Just retry on errors */
- + if ((bds & TNTUSB_BD_STATE_MSK) == TNTUSB_BD_STATE_DONE_ERR) {
- + tntusb_ep_regs[epnum].out.bd[0].csr = TNTUSB_BD_STATE_RDY_DATA | TNTUSB_BD_LEN(xf->mps);
- + return true;
- + }
- +
- + /* Packet done */
- + if ((bds & TNTUSB_BD_STATE_MSK) == TNTUSB_BD_STATE_DONE_OK)
- + {
- + xf->plen = (bds & TNTUSB_BD_LEN_MSK) - 2;
- + if (xf->plen > (xf->len - xf->ofs))
- + xf->plen = xf->len - xf->ofs;
- +
- + tntusb_ep_regs[epnum].out.bd[0].csr = 0;
- +
- + if (xf->plen) {
- + _usb_data_read(&xf->buf[xf->ofs], tntusb_ep_regs[epnum].out.bd[0].ptr, xf->plen);
- + xf->ofs += xf->plen;
- + }
- +
- + /* end of transfer when requested length is reached, or a short transfer from host */
- + if ((xf->plen < xf->mps) || (xf->len == xf->ofs))
- + {
- + len = xf->ofs;
- +
- + xf->buf = NULL;
- + xf->len = 0;
- + xf->ofs = 0;
- + xf->plen = 0;
- +
- + dcd_event_xfer_complete(0, epnum, len, XFER_RESULT_SUCCESS, true);
- + }
- +
- + pkt_done = true;
- + }
- +
- + /* Need to submit another one */
- + if (pkt_done || ((bds & TNTUSB_BD_STATE_MSK) == TNTUSB_BD_STATE_NONE))
- + {
- + if (xf->buf)
- + tntusb_ep_regs[epnum].out.bd[0].csr = TNTUSB_BD_STATE_RDY_DATA | TNTUSB_BD_LEN(xf->mps);
- + return true;
- + }
- +
- + return pkt_done;
- +}
- +
- bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) {
- (void) rhport;
- uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress);
- uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress);
- - g_usb.ep_mps[epnum]=desc_edpt->wMaxPacketSize.size;
- +
- + g_usb.xfer[epnum][dir].mps = desc_edpt->wMaxPacketSize.size;
- int type=0;
- if (desc_edpt->bmAttributes.xfer==TUSB_XFER_CONTROL) type=TNTUSB_EP_TYPE_CTRL;
- @@ -154,12 +288,16 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) {
- g_usb.mem_free_ptr_out+=desc_edpt->wMaxPacketSize.size+8; //add setup packet
- g_usb.mem_free_ptr_in+=desc_edpt->wMaxPacketSize.size;
- +
- + g_usb.xfer[0][TUSB_DIR_IN].mps = desc_edpt->wMaxPacketSize.size;
- + g_usb.xfer[0][TUSB_DIR_OUT].mps = desc_edpt->wMaxPacketSize.size;
- +
- } else if (dir == TUSB_DIR_OUT) {
- printf("Setting up out endpoint %d\n", epnum);
- USB_CHECK(epnum!=0);
- tntusb_ep_regs[epnum].out.status = type;
- tntusb_ep_regs[epnum].out.bd[0].ptr = g_usb.mem_free_ptr_out;
- - tntusb_ep_regs[epnum].out.bd[0].csr = TNTUSB_BD_STATE_RDY_DATA | TNTUSB_BD_LEN(desc_edpt->wMaxPacketSize.size);
- + tntusb_ep_regs[epnum].out.bd[0].csr = 0;
- g_usb.mem_free_ptr_out+=desc_edpt->wMaxPacketSize.size;
- } else {
- printf("Setting up in endpoint %d\n", epnum);
- @@ -177,31 +315,73 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
- - printf ("dcd_edpt_xfer: ep %d dir %s, len %d\n", epnum, (dir==TUSB_DIR_OUT)?"out":"in", total_bytes);
- -
- - if (dir==TUSB_DIR_OUT) {
- - if (buffer) _usb_data_read(buffer, tntusb_ep_regs[epnum].out.bd[0].ptr, total_bytes);
- - tntusb_ep_regs[epnum].out.bd[0].csr = TNTUSB_BD_STATE_RDY_DATA | TNTUSB_BD_LEN(g_usb.ep_mps[epnum]);
- - } else {
- - if (buffer) _usb_data_write(tntusb_ep_regs[epnum].in.bd[0].ptr, buffer, total_bytes);
- - tntusb_ep_regs[epnum].in.bd[0].csr = TNTUSB_BD_STATE_RDY_DATA | TNTUSB_BD_LEN(total_bytes);
- - g_usb.ep_in_xfer_len[epnum]=total_bytes;
- + printf ("dcd_edpt_xfer: ep %d dir %s, len %d, buf %08x\n", epnum, (dir==TUSB_DIR_OUT)?"out":"in", total_bytes, buffer);
- +
- + g_usb.xfer[epnum][dir].buf = buffer;
- + g_usb.xfer[epnum][dir].len = total_bytes;
- + g_usb.xfer[epnum][dir].ofs = 0;
- +
- + if (!buffer) {
- + /* ZLP */
- + if (dir == TUSB_DIR_IN) {
- + tntusb_ep_regs[epnum].in.bd[0].csr = TNTUSB_BD_STATE_RDY_DATA | TNTUSB_BD_LEN(0);
- + } else {
- + tntusb_ep_regs[epnum].out.bd[0].csr = TNTUSB_BD_STATE_RDY_DATA | TNTUSB_BD_LEN(0);
- + }
- }
- +
- + if (dir == TUSB_DIR_OUT)
- + _ep_advance_xfer_out(epnum);
- + else
- + _ep_advance_xfer_in(epnum);
- +
- return true;
- }
- void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) {
- (void) rhport;
- printf("STALL ep %d\n", ep_addr);
- +
- uint8_t const epnum = tu_edpt_number(ep_addr);
- - tntusb_ep_regs[epnum].out.bd[0].csr |= TNTUSB_BD_STATE_RDY_STALL;
- + uint8_t const dir = tu_edpt_dir(ep_addr);
- +
- + if (epnum == 0) {
- + /* For EP0 we can't halt it since we still need to receive SETUP */
- + /* So we need to manually queue STALL */
- + if (dir == TUSB_DIR_OUT) {
- + g_usb.ep0_stall = true;
- + tntusb_ep_regs[epnum].out.bd[0].csr = TNTUSB_BD_STATE_RDY_STALL;
- + } else {
- + g_usb.ep0_stall = true;
- + tntusb_ep_regs[epnum].in.bd[0].csr = TNTUSB_BD_STATE_RDY_STALL;
- + }
- + } else {
- + /* Simply halt the end point */
- + if (dir == TUSB_DIR_OUT) {
- + tntusb_ep_regs[epnum].out.status |= TNTUSB_EP_TYPE_HALTED;
- + } else {
- + tntusb_ep_regs[epnum].in.status |= TNTUSB_EP_TYPE_HALTED;
- + }
- + }
- }
- void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) {
- (void) rhport;
- printf("UNSTALL ep %d\n", ep_addr);
- +
- uint8_t const epnum = tu_edpt_number(ep_addr);
- - tntusb_ep_regs[epnum].out.bd[0].csr &= ~TNTUSB_BD_STATE_RDY_STALL;
- + uint8_t const dir = tu_edpt_dir(ep_addr);
- +
- + if (epnum == 0) {
- + /* This is handled when we get a SETUP packet */
- + } else {
- + /* Resume the end point */
- + if (dir == TUSB_DIR_OUT) {
- + tntusb_ep_regs[epnum].out.status &= ~TNTUSB_EP_TYPE_HALTED;
- + } else {
- + tntusb_ep_regs[epnum].in.status &= ~TNTUSB_EP_TYPE_HALTED;
- + }
- + }
- }
- /*------------------------------------------------------------------*/
- @@ -216,6 +396,7 @@ void usb_poll(void) {
- }
- printf("Reset pending: doing that\n");
- _usb_hw_reset(true);
- + memset(&g_usb.xfer, 0x00, sizeof(g_usb.xfer));
- dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true);
- g_usb.mem_free_ptr_out=0;
- g_usb.mem_free_ptr_in=0;
- @@ -232,37 +413,41 @@ void usb_poll(void) {
- dcd_event_bus_signal(0, DCD_EVENT_SOF, true);
- }
- - //setup handling
- - uint32_t bds_setup=tntusb_ep_regs[0].out.bd[1].csr;
- - if ((tntusb_ep_regs[0].out.bd[1].csr & TNTUSB_BD_STATE_MSK) == TNTUSB_BD_STATE_DONE_OK) {
- - //Setup packet received. Read and ack manually.
- + // Handle endpoints
- + for (int ep=0; ep<16; ep++) {
- + _ep_advance_xfer_in(ep);
- + _ep_advance_xfer_out(ep);
- + }
- +
- + // Setup handling
- + uint32_t bds_setup = tntusb_ep_regs[0].out.bd[1].csr;
- +
- + if ((bds_setup & TNTUSB_BD_STATE_MSK) == TNTUSB_BD_STATE_DONE_OK) {
- + // Setup packet received. Read and ack manually.
- _usb_data_read(tmpbuf, tntusb_ep_regs[0].out.bd[1].ptr, 8);
- printf("Setup packet rcvd:");
- for (int i=0; i<8; i++) printf("%02X ", tmpbuf[i]);
- printf("\n");
- tntusb_ep_regs[0].out.bd[1].csr = TNTUSB_BD_STATE_RDY_DATA | TNTUSB_BD_LEN(8);
- - //clear in/out
- +
- + // Clear in/out/stall
- tntusb_ep_regs[0].in.bd[0].csr = 0;
- tntusb_ep_regs[0].out.bd[0].csr = 0;
- - //Make sure DT=1 for IN endpoint after a SETUP
- + g_usb.ep0_stall = false;
- +
- + // Release lockout
- + tntusb_regs->ar = TNTUSB_AR_CEL_RELEASE;
- +
- + // Make sure DT=1 for IN endpoint after a SETUP
- tntusb_ep_regs[0].in.status = TNTUSB_EP_TYPE_CTRL | TNTUSB_EP_DT_BIT;
- +
- + // Notify tinyusb stack
- dcd_event_setup_received(0, tmpbuf, true);
- - tntusb_regs->ar = TNTUSB_AR_CEL_RELEASE;
- - }
- + } else if ((bds_setup & TNTUSB_BD_STATE_MSK) == TNTUSB_BD_STATE_DONE_ERR) {
- + /* Just setup a new one ... */
- + tntusb_ep_regs[0].out.bd[1].csr = TNTUSB_BD_STATE_RDY_DATA | TNTUSB_BD_LEN(8);
- - //handle endpoints
- - for (int ep=0; ep<16; ep++) {
- - uint32_t in_csr=tntusb_ep_regs[ep].in.bd[0].csr;
- - if ((in_csr & TNTUSB_BD_STATE_MSK) == TNTUSB_BD_STATE_DONE_OK) {
- - printf("IN xfer done on ep %d: %d bytes\n", ep, g_usb.ep_in_xfer_len[ep]);
- - tntusb_ep_regs[ep].in.bd[0].csr=0;
- - dcd_event_xfer_complete(0, ep, g_usb.ep_in_xfer_len[ep], XFER_RESULT_SUCCESS, true);
- - }
- - uint32_t out_csr=tntusb_ep_regs[ep].out.bd[0].csr;
- - if ((out_csr & TNTUSB_BD_STATE_MSK) == TNTUSB_BD_STATE_DONE_OK) {
- - printf("OUT xfer done on ep %d: %d bytes\n", ep, out_csr & TNTUSB_BD_LEN_MSK);
- - dcd_event_xfer_complete(0, ep, out_csr & TNTUSB_BD_LEN_MSK, XFER_RESULT_SUCCESS, true);
- - }
- + /* FIXME: can't check of the lockout is triggered if an error happens ... */
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment