esp32s2 tinyusb vendor device小总结

usb 802.11 wifi网卡,遇到点问题。

对tinyusb的架构有一点小了解了。

发送路径:

用户调用tud_vendor_write(urb_msg,urb_len);    启动传输

tud_vendor_write()

>tud_vendor_n_write(0, buffer, bufsize);

>>tu_fifo_write_n(&p_itf->tx_ff, buffer, bufsize) 写入fifo缓冲

>>maybe_transmit(p_itf) 尝试启动硬件传输

>>>usbd_edpt_busy(TUD_OPT_RHPORT, p_itf->ep_in)  check busy

>>>u_fifo_read_n(&p_itf->tx_ff, p_itf->epin_buf, CFG_TUD_VENDOR_EPSIZE); read data from fifo

>>>usbd_edpt_xfer(TUD_OPT_RHPORT, p_itf->ep_in, p_itf->epin_buf, count) ); start hardware xfer

>>>>dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes)  portable part

esp-idf-4.3-beta3\esp-idf-4.3-beta3\components\tinyusb\tinyusb\src\portable\espressif\esp32s2\dcd_esp32s2.c

esp32s2目前没有用DMA模式,是cpu模式,配置packet数量和size.

USB0.in_ep_reg[epnum].dieptsiz = (num_packets << USB_D_PKTCNT0_S) | total_bytes;

启动ep和清NAK要启动

 USB0.in_ep_reg[epnum].diepctl |= USB_D_EPENA1_M | USB_D_CNAK1_M; // Enable | CNAK

全能fifo empty中断

USB0.dtknqr4_fifoemptymsk |= (1 << epnum);

然后是中断推动方式。中断关系可以参考手册,里面讲了大的关系,小的没讲。

void handle_epin_ints(void)

 if (int_status & USB_IEPINT_M) {  
    // IEPINT bit read-only
    ESP_EARLY_LOGV(TAG, "dcd_int_handler - IN endpoint!");
    handle_epin_ints();
  }

遍历所有的中断,查找中断endpoint.

 if (USB0.daint & (1 << (0 + n))) {

收到完成中断,表明所有的数据成功传输

  if (USB0.in_ep_reg[n].diepint & USB_D_XFERCOMPL0_M)

调用d_event_xfer_complete(0, n | TUSB_DIR_IN_MASK)通知事件,

然后在tu_task()回调驱动的完成函数,再次启动maybe_transmit(p_itf)准备下一个数据包传输。

 if (USB0.in_ep_reg[n].diepint & USB_D_TXFEMP0_M) { fifo空了,

填写fifo数据,以32bit方式写入。

 transmit_packet(xfer, &USB0.in_ep_reg[n], n);

> remaining = (in_ep->dieptsiz & 0x7FFFFU) >> USB_D_XFERSIZE0_S;获取传输剩余数据长度,确定写入长度,一次最多写max_ep_size.

然后要说的是USB0.in_ep_reg[epnum].dieptsiz [19-21]是包数,每成功传输一个包就会减一。另外USB0.in_ep_reg[epnum].dtxfsts是fifo的可用长度,每成功传输就会少对应的32bit值。

当fifo传输完成,就会传输完成中断assert.(我根据实验猜测的)。因为我发现in_ep->dieptsiz的remaining为0,并不会将packet_cnt清掉。

接收路径:

vendord_open()

>!usbd_edpt_xfer(rhport, p_vendor->ep_out, p_vendor->epout_buf, sizeof(p_vendor->epout_buf)) ) 配置硬件接收数据。

>>dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes)

   // Each complete packet for OUT xfers triggers XFRC. 每次只能接收一个包
    USB0.out_ep_reg[epnum].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S);

使能ep,清NAK. 
    USB0.out_ep_reg[epnum].doepctl  |= USB_EPENA0_M | USB_CNAK0_M;

中断推动:

_dcd_int_handler(void* arg)

 if (int_status & USB_RXFLVI_M) {
    // RXFLVL bit is read-only
    ESP_EARLY_LOGV(TAG, "dcd_int_handler - rx!");

    // Mask out RXFLVL while reading data from FIFO
    USB0.gintmsk &= ~USB_RXFLVIMSK_M;
    read_rx_fifo(); 读取fifo,会更新对应传输的接收xfer->queued_len,并且会设置short_packet如果是的,
    USB0.gintmsk |= USB_RXFLVIMSK_M;
  }

  // OUT endpoint interrupt handling.
  if (int_status & USB_OEPINT_M) {
    // OEPINT is read-only
    handle_epout_ints(); 输出中断来了,
  }

 if (xfer->short_packet || (xfer->queued_len == xfer->total_len)) {
          xfer->short_packet = false; 传输结果,就通知上层,
          dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true);
        } else {
          // Schedule another packet to be received. 启动下一个包接收工作。
          USB0.out_ep_reg[n].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S);
          USB0.out_ep_reg[n].doepctl |= USB_EPENA0_M | USB_CNAK0_M;
        }

你可能感兴趣的:(DIY,总结,物联网,c语言,linux)