[资料工具] NV32 F00x LemcUSB

[复制链接]
 楼主| hanzhen654 发表于 2020-3-29 14:36 | 显示全部楼层 |阅读模式

USB重启接收
  1. void usb_reset_received(void)
  2. {  
  3.   uint32_t cnt;
  4.   uint32_t *ptr;
  5.   
  6.   GPIOA->PSOR = (1<<1);
  7.   
  8.   /* zero intitialize endpoint buffers and len/status fields */
  9.   ptr = (uint32_t *)usb_ep_buffers;
  10.   for (cnt=0; cnt < (sizeof(usb_ep_buffers)>>2); cnt++)
  11.   {
  12.     *ptr++ = 0;
  13.   }
  14.   
  15.   /* preinitialize DATA PIDS for IN endpoints */
  16.   usb_ep_buffers[USB_EPBUF_OFFSET_EP0IN_BUF] = 0x4B;
  17.   usb_ep_buffers[USB_EPBUF_OFFSET_EP1IN_BUF] = 0x4B;

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


 楼主| hanzhen654 发表于 2020-3-29 14:40 | 显示全部楼层
USB 初始化函数
  1. void usb_init(void)
  2. {
  3.   usb_reset_received();
  4.   
  5.   /* Pinout: PA1 = USB connect line (1k5 resistor to PC0)
  6.              PA2 = D-
  7.              PA3 = D+
  8.   */
  9.   /* set PA0 low (disconnected) Will enable the pulldown */
  10.   GPIOA->PCOR = (1 << 2);
  11.   /* Pin PA0 is configured to Input enabled with pull-down */
  12.   //GPIO->P[0].MODEL = (GPIO->P[0].MODEL & ~_GPIO_P_MODEL_MODE0_MASK) | GPIO_P_MODEL_MODE0_INPUTPULL;

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

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

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


 楼主| 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);
}
 楼主| 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;
}
 楼主| hanzhen654 发表于 2020-3-29 14:46 | 显示全部楼层
USB从安装中得到数据
  1. void usb_setup_get_data(setupData_t *psetupdata)
  2. {
  3.   uint32_t i, j;
  4.   uint8_t  dat;
  5.   uint8_t  setupdat[8];
  6.   volatile uint8_t *SETUP_BUF;
  7.   
  8.   SETUP_BUF = &usb_ep_buffers[USB_EPBUF_OFFSET_SETUP_BUF];
  9.   for (i=0; i<8; i++) /* walk through all bytes */
  10.   {
  11.     j = i+1;
  12.     j = (j & 0xfC) | (3-(j & 0x03)); /* reverse byteorder => TODO: This can be done in the .s file using the REV instruction (single cycle) */
  13.     dat = SETUP_BUF[j];
  14.     dat = bitreverse(dat);           /* reverse bits*/
  15.     setupdat[i] = dat;               /* store data */
  16.   }
  17.   usb_ep_buffers[USB_EPBUF_OFFSET_SETUP_BUF + USB_EPBUF_SUBOFFSET_STAT] &= ~(1 << 0); /* flag setup data as empty */
  18.   
  19.   psetupdata->bmRequestType = setupdat[0];
  20.   psetupdata->bRequest      = setupdat[1];
  21.   psetupdata->wValue        = setupdat[2];
  22.   psetupdata->wValue       |= setupdat[3] << 8;
  23.   psetupdata->wIndex        = setupdat[4];
  24.   psetupdata->wIndex       |= setupdat[5] << 8;
  25.   psetupdata->wLength       = setupdat[6];
  26.   psetupdata->wLength      |= setupdat[7] << 8;
  27. }


 楼主| hanzhen654 发表于 2020-3-29 14:46 | 显示全部楼层
判断USB buf是否为空
  1. bool usb_ep_in_buf_empty(uint32_t epnum)
  2. {
  3.   if (epnum)
  4.   {
  5.     return (usb_ep_buffers[USB_EPBUF_OFFSET_EP1IN_BUF + USB_EPBUF_SUBOFFSET_STAT] & (1 << 0)) == 0x00;
  6.   }
  7.   else
  8.   {
  9.     return (usb_ep_buffers[USB_EPBUF_OFFSET_EP0IN_BUF + USB_EPBUF_SUBOFFSET_STAT] & (1 << 0)) == 0x00;
  10.   }
  11. }


 楼主| hanzhen654 发表于 2020-3-29 14:47 | 显示全部楼层
检查相关参数是否有效
  1. void usb_ep_in_commit_pkt(uint32_t epnum, bool firstpkt, const uint8_t *pbuf, uint32_t len)
  2. {
  3.   uint32_t i;
  4.   uint8_t  dat;
  5.   uint16_t crc_value;
  6.   volatile uint8_t *EP0IN_BUF;
  7.   
  8.   if (!len)
  9.   {
  10.     GPIOA->PSOR = (1<<8);
  11.     GPIOA->PCOR = (1<<8);
  12.   }
  13.   
  14.   if (epnum)
  15.   {
  16.     EP0IN_BUF = &usb_ep_buffers[USB_EPBUF_OFFSET_EP1IN_BUF];
  17.   }
  18.   else
  19.   {
  20.     EP0IN_BUF = &usb_ep_buffers[USB_EPBUF_OFFSET_EP0IN_BUF];
  21.   }
  22.   
  23.   if (firstpkt)
  24.   {   
  25.     EP0IN_BUF[0] = 0x4B;   /* first IN packet is always transmitted with DATA1 PID */
  26.   }
  27.   else
  28.   {
  29.     EP0IN_BUF[0] ^= 0x88; /* Following packets toggle between DATA0 and DATA1 PID */
  30.   }
  31.   
  32.   crc_value = 0xffff;
  33.   for (i=0; i<len; i++)
  34.   {
  35.     dat = *pbuf++;
  36.     EP0IN_BUF[i+1] = dat;
  37.     crc_value = crc16(crc_value, dat);
  38.   }
  39.   
  40.   crc_value = ~crc_value; /* this is described in the USB spec. */
  41.   
  42.   /* ADD CRC */
  43.   EP0IN_BUF[1+len+0] = crc_value & 0xff;   /* CRC low */
  44.   EP0IN_BUF[1+len+1] = crc_value >> 8;     /* CRC high */

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


 楼主| hanzhen654 发表于 2020-3-29 14:48 | 显示全部楼层
USB ep输出有效数据
  1. bool usb_ep_out_data_available(uint32_t epnum)
  2. {
  3.   if (epnum == 0x00)
  4.   {
  5.     return (usb_ep_buffers[USB_EPBUF_OFFSET_EP0OUT_BUF + USB_EPBUF_SUBOFFSET_STAT] & (1 << 0)) != 0x00;
  6.   }
  7.   else
  8.   {
  9.     return (usb_ep_buffers[USB_EPBUF_OFFSET_EP1OUT_BUF + USB_EPBUF_SUBOFFSET_STAT] & (1 << 0)) != 0x00;
  10.   }
  11. }


 楼主| hanzhen654 发表于 2020-3-29 14:49 | 显示全部楼层
从ep中获得有效数据
  1. uint32_t usb_ep_out_get_data(uint32_t epnum, uint8_t *pbuf)
  2. {
  3.   uint32_t i, j, len;
  4.   uint8_t  dat, bytecount;
  5.   volatile uint8_t *EP0OUT_BUF;
  6.    
  7.   if (epnum == 0)
  8.   {
  9.     EP0OUT_BUF = &usb_ep_buffers[USB_EPBUF_OFFSET_EP0OUT_BUF];
  10.   }
  11.   else
  12.   {   
  13.     EP0OUT_BUF = &usb_ep_buffers[USB_EPBUF_OFFSET_EP1OUT_BUF];
  14.   }

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

  26.   //bytecount = 0;
  27.   
  28.   if (bytecount > 0)
  29.   {
  30.     volatile int i;
  31.     i=0;
  32.   }

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

  36.   return bytecount;
  37. }


 楼主| hanzhen654 发表于 2020-3-29 14:51 | 显示全部楼层
通过EP0发送一个长度为7字节的包
  1. void usb_ep_in_commit_pkt_long(uint32_t epnum, const uint8_t *pbuf, uint8_t len, bool sendshortpkt)
  2. {
  3.   bool    first;
  4.   uint8_t curlen;
  5.   
  6.   first = (epnum == 0x00); /* EP0IN packets always start with DATA1 PID, while EP1IN PID toggles between DATA0/1 */

  7.   curlen = 0;
  8.   
  9.   while (len)
  10.   {
  11.     curlen = len;
  12.     if (curlen > 8)
  13.     {
  14.       curlen = 8;
  15.     }   
  16.     while (!usb_ep_in_buf_empty(epnum)); /* wait until endpoint buffer is free */
  17.     usb_ep_in_commit_pkt(epnum, first, pbuf, curlen);
  18.     len  -= curlen;
  19.     pbuf += curlen;
  20.     first = false;
  21.   }
  22.   if (!sendshortpkt)
  23.   {
  24.     return;
  25.   }
  26.   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*/
  27.   {
  28.     while (!usb_ep_in_buf_empty(epnum));  /* wait until endpoint buffer is free */
  29.     usb_ep_in_commit_pkt(epnum, false, pbuf, 0);
  30.   }
  31. }


 楼主| hanzhen654 发表于 2020-3-29 14:54 | 显示全部楼层
通过EP0OUT接收包裹。允许大于8字节
  1. uint8_t usb_ep_out_get_data_long(uint8_t *pbuf, uint8_t maxlen)
  2. {
  3.   uint8_t curlen, len;

  4.   curlen = 8;
  5.   len = 0;
  6.   do
  7.   {
  8.     if (usb_ep_out_data_available(0))
  9.     {
  10.       curlen = usb_ep_out_get_data(0, pbuf);    /* TODO: Handle this within usb_stack.c. It is part of control transfers. setup */
  11.       pbuf += curlen;
  12.       if (len >= maxlen) /* at least a little bit of protection against buffer overruns */
  13.       {
  14.         pbuf -= curlen;
  15.       }
  16.       len += curlen;
  17.     }   
  18.   } while ( (curlen == 8) && (len < maxlen) ); /* a short packet indicates the last packet */
  19.   return len;
  20. }


 楼主| hanzhen654 发表于 2020-3-29 14:55 | 显示全部楼层
在没有数据阶段的情况下处理控制传输
  1. void usb_control_acknowledge(void)
  2. {
  3.   uint8_t response[8];
  4.   while (!usb_ep_in_buf_empty(0x00))
  5.     ;
  6.   usb_ep_in_commit_pkt(0, true, response, 0);  
  7. }


 楼主| hanzhen654 发表于 2020-3-29 14:56 | 显示全部楼层
在传输中处理控件
  1. bool usb_control_dataIn(const uint8_t *pbuf, uint8_t len)
  2. {
  3.   usb_ep_in_commit_pkt_long(0, pbuf, len, false);//true);
  4.   /* wait for status stage - acknowledge from HOST*/
  5.   while ( !usb_ep_out_data_available(0) )
  6.   {   
  7.   }
  8.   usb_ep_buffers[USB_EPBUF_OFFSET_EP0OUT_BUF + USB_EPBUF_SUBOFFSET_STAT] &= ~(1 << 0); /* ignore ACK (OUT packet) */
  9.   return true;
  10. }


 楼主| 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

粉丝
快速回复 在线客服 返回列表 返回顶部

73

主题

1766

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部