打印
[资料工具]

NV32 F00x LemcUSB

[复制链接]
615|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hanzhen654|  楼主 | 2020-3-29 14:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

USB重启接收
void usb_reset_received(void)
{  
  uint32_t cnt;
  uint32_t *ptr;
  
  GPIOA->PSOR = (1<<1);
  
  /* zero intitialize endpoint buffers and len/status fields */
  ptr = (uint32_t *)usb_ep_buffers;
  for (cnt=0; cnt < (sizeof(usb_ep_buffers)>>2); cnt++)
  {
    *ptr++ = 0;
  }
  
  /* preinitialize DATA PIDS for IN endpoints */
  usb_ep_buffers[USB_EPBUF_OFFSET_EP0IN_BUF] = 0x4B;
  usb_ep_buffers[USB_EPBUF_OFFSET_EP1IN_BUF] = 0x4B;

  /* reset usb device address to 0 (will be changed during enumeration) */
  usbstack_init();
  GPIOA->PSOR = (1<<1);
}


使用特权

评论回复

相关帖子

沙发
hanzhen654|  楼主 | 2020-3-29 14:40 | 只看该作者
USB 初始化函数
void usb_init(void)
{
  usb_reset_received();
  
  /* Pinout: PA1 = USB connect line (1k5 resistor to PC0)
             PA2 = D-
             PA3 = D+
  */
  /* set PA0 low (disconnected) Will enable the pulldown */
  GPIOA->PCOR = (1 << 2);
  /* Pin PA0 is configured to Input enabled with pull-down */
  //GPIO->P[0].MODEL = (GPIO->P[0].MODEL & ~_GPIO_P_MODEL_MODE0_MASK) | GPIO_P_MODEL_MODE0_INPUTPULL;

  /* Pin PC0 is configured to Input enabled */
  //GPIO->P[2].MODEL = (GPIO->P[2].MODEL & ~_GPIO_P_MODEL_MODE0_MASK) | GPIO_P_MODEL_MODE0_INPUT;
  /* Pin PC1 is configured to Input enabled */
// GPIO->P[2].MODEL = (GPIO->P[2].MODEL & ~_GPIO_P_MODEL_MODE1_MASK) | GPIO_P_MODEL_MODE1_INPUT;
  
  /* set output state of PC0 PC1 (D- D+) to 1 0 */
  GPIOA->PSOR = (1<<2); /* D- = 1 */
  GPIOA->PCOR = (1<<3); /* D+ = 0 */

  /* Pin PE13 is configured to Push-pull */
  //GPIO->P[4].MODEH = (GPIO->P[4].MODEH & ~_GPIO_P_MODEH_MODE13_MASK) | GPIO_P_MODEH_MODE13_PUSHPULL;

  /* setup PC1 interrupt on rising edge (D+ first SYNC bit) */  
  /* Configure PC1 interrupt on rising edge */
// GPIO_IntConfig(gpioPortC, 1, true, false, true);
  /* Set Interrupt priority to highest */
//  NVIC_SetPriority(GPIO_ODD_IRQn, 0);
  /* Enable GPIO_EVEN interrupt vector in NVIC */
// NVIC_EnableIRQ(GPIO_ODD_IRQn);
}


使用特权

评论回复
板凳
hanzhen654|  楼主 | 2020-3-29 14:41 | 只看该作者
USB连接函数
void usb_connect(void)
{
  GPIOA->PSOR = (1 << 3);
  //GPIO->P[0].MODEL = (GPIO->P[0].MODEL & ~_GPIO_P_MODEL_MODE0_MASK) | GPIO_P_MODEL_MODE0_PUSHPULL;  
}

使用特权

评论回复
地板
hanzhen654|  楼主 | 2020-3-29 14:43 | 只看该作者
USB断开函数
void usb_disconnect(void)
{
  /* Pin PA0 is configured to Input enabled with pull-down */
// GPIO->P[0].MODEL = (GPIO->P[0].MODEL & ~_GPIO_P_MODEL_MODE0_MASK) | GPIO_P_MODEL_MODE0_INPUTPULL;
  /* set PA0 low (disconnected) Will enable the pulldown */
GPIOA->PCOR = (1 << 3);
}

使用特权

评论回复
5
hanzhen654|  楼主 | 2020-3-29 14:44 | 只看该作者
检查是否收到安装包
bool usb_setup_available(void)
{
  return (usb_ep_buffers[USB_EPBUF_OFFSET_SETUP_BUF + USB_EPBUF_SUBOFFSET_STAT] & (1 << 0)) != 0x00;
}

使用特权

评论回复
6
hanzhen654|  楼主 | 2020-3-29 14:46 | 只看该作者
USB从安装中得到数据
void usb_setup_get_data(setupData_t *psetupdata)
{
  uint32_t i, j;
  uint8_t  dat;
  uint8_t  setupdat[8];
  volatile uint8_t *SETUP_BUF;
  
  SETUP_BUF = &usb_ep_buffers[USB_EPBUF_OFFSET_SETUP_BUF];
  for (i=0; i<8; i++) /* walk through all bytes */
  {
    j = i+1;
    j = (j & 0xfC) | (3-(j & 0x03)); /* reverse byteorder => TODO: This can be done in the .s file using the REV instruction (single cycle) */
    dat = SETUP_BUF[j];
    dat = bitreverse(dat);           /* reverse bits*/
    setupdat[i] = dat;               /* store data */
  }
  usb_ep_buffers[USB_EPBUF_OFFSET_SETUP_BUF + USB_EPBUF_SUBOFFSET_STAT] &= ~(1 << 0); /* flag setup data as empty */
  
  psetupdata->bmRequestType = setupdat[0];
  psetupdata->bRequest      = setupdat[1];
  psetupdata->wValue        = setupdat[2];
  psetupdata->wValue       |= setupdat[3] << 8;
  psetupdata->wIndex        = setupdat[4];
  psetupdata->wIndex       |= setupdat[5] << 8;
  psetupdata->wLength       = setupdat[6];
  psetupdata->wLength      |= setupdat[7] << 8;
}


使用特权

评论回复
7
hanzhen654|  楼主 | 2020-3-29 14:46 | 只看该作者
判断USB buf是否为空
bool usb_ep_in_buf_empty(uint32_t epnum)
{
  if (epnum)
  {
    return (usb_ep_buffers[USB_EPBUF_OFFSET_EP1IN_BUF + USB_EPBUF_SUBOFFSET_STAT] & (1 << 0)) == 0x00;
  }
  else
  {
    return (usb_ep_buffers[USB_EPBUF_OFFSET_EP0IN_BUF + USB_EPBUF_SUBOFFSET_STAT] & (1 << 0)) == 0x00;
  }
}


使用特权

评论回复
8
hanzhen654|  楼主 | 2020-3-29 14:47 | 只看该作者
检查相关参数是否有效
void usb_ep_in_commit_pkt(uint32_t epnum, bool firstpkt, const uint8_t *pbuf, uint32_t len)
{
  uint32_t i;
  uint8_t  dat;
  uint16_t crc_value;
  volatile uint8_t *EP0IN_BUF;
  
  if (!len)
  {
    GPIOA->PSOR = (1<<8);
    GPIOA->PCOR = (1<<8);
  }
  
  if (epnum)
  {
    EP0IN_BUF = &usb_ep_buffers[USB_EPBUF_OFFSET_EP1IN_BUF];
  }
  else
  {
    EP0IN_BUF = &usb_ep_buffers[USB_EPBUF_OFFSET_EP0IN_BUF];
  }
  
  if (firstpkt)
  {   
    EP0IN_BUF[0] = 0x4B;   /* first IN packet is always transmitted with DATA1 PID */
  }
  else
  {
    EP0IN_BUF[0] ^= 0x88; /* Following packets toggle between DATA0 and DATA1 PID */
  }
  
  crc_value = 0xffff;
  for (i=0; i<len; i++)
  {
    dat = *pbuf++;
    EP0IN_BUF[i+1] = dat;
    crc_value = crc16(crc_value, dat);
  }
  
  crc_value = ~crc_value; /* this is described in the USB spec. */
  
  /* ADD CRC */
  EP0IN_BUF[1+len+0] = crc_value & 0xff;   /* CRC low */
  EP0IN_BUF[1+len+1] = crc_value >> 8;     /* CRC high */

  /* set packet length */  
  EP0IN_BUF[USB_EPBUF_SUBOFFSET_LEN] = len + 1 +2; /* DATAx PID + CRC16 */
  
  /* Flag endpoint as "ready" for transmission. This needs to be done as the last step */
  EP0IN_BUF[USB_EPBUF_SUBOFFSET_STAT] |= (1 << 0);
}


使用特权

评论回复
9
hanzhen654|  楼主 | 2020-3-29 14:48 | 只看该作者
USB ep输出有效数据
bool usb_ep_out_data_available(uint32_t epnum)
{
  if (epnum == 0x00)
  {
    return (usb_ep_buffers[USB_EPBUF_OFFSET_EP0OUT_BUF + USB_EPBUF_SUBOFFSET_STAT] & (1 << 0)) != 0x00;
  }
  else
  {
    return (usb_ep_buffers[USB_EPBUF_OFFSET_EP1OUT_BUF + USB_EPBUF_SUBOFFSET_STAT] & (1 << 0)) != 0x00;
  }
}


使用特权

评论回复
10
hanzhen654|  楼主 | 2020-3-29 14:49 | 只看该作者
从ep中获得有效数据
uint32_t usb_ep_out_get_data(uint32_t epnum, uint8_t *pbuf)
{
  uint32_t i, j, len;
  uint8_t  dat, bytecount;
  volatile uint8_t *EP0OUT_BUF;
   
  if (epnum == 0)
  {
    EP0OUT_BUF = &usb_ep_buffers[USB_EPBUF_OFFSET_EP0OUT_BUF];
  }
  else
  {   
    EP0OUT_BUF = &usb_ep_buffers[USB_EPBUF_OFFSET_EP1OUT_BUF];
  }

  len = EP0OUT_BUF[USB_EPBUF_SUBOFFSET_LEN];
  bytecount = ((len + 7) >> 3) - 1 - 2; /* -PID -CRC16 */
  
  for (i=0; i<bytecount; i++) /* walk through all bytes */
  {
    j = i+1;
    j = (j & 0xfC) | (3-(j & 0x03)); /* reverse byteorder => TODO: This can be done in the .s file using the REV instruction (single cycle) */
    dat = EP0OUT_BUF[j];
    dat = bitreverse(dat);        /* reverse bits*/
    *pbuf++ = dat;                /* store data */
  }

  //bytecount = 0;
  
  if (bytecount > 0)
  {
    volatile int i;
    i=0;
  }

  /* flag endpoint as empty. Needs to be done as last step */
  EP0OUT_BUF[USB_EPBUF_SUBOFFSET_STAT]  &= ~(1 << 0);
  //usb_ep_buffers[USB_EPBUF_OFFSET_EP0OUT_BUF + USB_EPBUF_SUBOFFSET_STAT] &= ~(1 << 0);

  return bytecount;
}


使用特权

评论回复
11
hanzhen654|  楼主 | 2020-3-29 14:51 | 只看该作者
通过EP0发送一个长度为7字节的包
void usb_ep_in_commit_pkt_long(uint32_t epnum, const uint8_t *pbuf, uint8_t len, bool sendshortpkt)
{
  bool    first;
  uint8_t curlen;
  
  first = (epnum == 0x00); /* EP0IN packets always start with DATA1 PID, while EP1IN PID toggles between DATA0/1 */

  curlen = 0;
  
  while (len)
  {
    curlen = len;
    if (curlen > 8)
    {
      curlen = 8;
    }   
    while (!usb_ep_in_buf_empty(epnum)); /* wait until endpoint buffer is free */
    usb_ep_in_commit_pkt(epnum, first, pbuf, curlen);
    len  -= curlen;
    pbuf += curlen;
    first = false;
  }
  if (!sendshortpkt)
  {
    return;
  }
  if ((curlen == 8) || (curlen == 0)) /* in case the last packet has 8 bytes a short packet needs to be sent to signalize the host, that this was the last packet*/
  {
    while (!usb_ep_in_buf_empty(epnum));  /* wait until endpoint buffer is free */
    usb_ep_in_commit_pkt(epnum, false, pbuf, 0);
  }
}


使用特权

评论回复
12
hanzhen654|  楼主 | 2020-3-29 14:54 | 只看该作者
通过EP0OUT接收包裹。允许大于8字节
uint8_t usb_ep_out_get_data_long(uint8_t *pbuf, uint8_t maxlen)
{
  uint8_t curlen, len;

  curlen = 8;
  len = 0;
  do
  {
    if (usb_ep_out_data_available(0))
    {
      curlen = usb_ep_out_get_data(0, pbuf);    /* TODO: Handle this within usb_stack.c. It is part of control transfers. setup */
      pbuf += curlen;
      if (len >= maxlen) /* at least a little bit of protection against buffer overruns */
      {
        pbuf -= curlen;
      }
      len += curlen;
    }   
  } while ( (curlen == 8) && (len < maxlen) ); /* a short packet indicates the last packet */
  return len;
}


使用特权

评论回复
13
hanzhen654|  楼主 | 2020-3-29 14:55 | 只看该作者
在没有数据阶段的情况下处理控制传输
void usb_control_acknowledge(void)
{
  uint8_t response[8];
  while (!usb_ep_in_buf_empty(0x00))
    ;
  usb_ep_in_commit_pkt(0, true, response, 0);  
}


使用特权

评论回复
14
hanzhen654|  楼主 | 2020-3-29 14:56 | 只看该作者
在传输中处理控件
bool usb_control_dataIn(const uint8_t *pbuf, uint8_t len)
{
  usb_ep_in_commit_pkt_long(0, pbuf, len, false);//true);
  /* wait for status stage - acknowledge from HOST*/
  while ( !usb_ep_out_data_available(0) )
  {   
  }
  usb_ep_buffers[USB_EPBUF_OFFSET_EP0OUT_BUF + USB_EPBUF_SUBOFFSET_STAT] &= ~(1 << 0); /* ignore ACK (OUT packet) */
  return true;
}


使用特权

评论回复
15
hanzhen654|  楼主 | 2020-3-29 14:59 | 只看该作者
处理控制输出传输
uint8_t usb_control_dataOut(uint8_t *pbuf, uint8_t maxlen)
{
  maxlen = usb_ep_out_get_data_long(pbuf, maxlen);
  usb_control_acknowledge();
  return maxlen;
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

73

主题

1766

帖子

2

粉丝