prottoss 0 7 ноября, 2015 Опубликовано 7 ноября, 2015 · Жалоба Продолжаю неспеша тупить с STM32. С Setup пакетами разобрался. Нужно вычитывать RX буфер сразу по приходу прерывания RXFLVL: RxFIFO non-empty. Прикрутил свою либу верхнего уровня с реализованным протоколом USB CDC. Все работает за исключением обработки запроса от хоста SET LINE CODING. В этом запросе две фазы. Первая SETUP - хост присылает 8 байт собственно запрос. Вторая DATA, где устройтсво должно принять собственно данные для установки порта - битрейт, четность и т.п. - 7 байт. Принятие данных организовываю так же в прерывании RXFLVL. Читаю OTG_FS->GRXSTSP. Количество байт - 7, статус - 0x02: /* OUT data packet received */. Все вроде четко. Вычитываю данные из FIFO, но вижу что данные не те, что нужно. В чем подвох? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 63 7 ноября, 2015 Опубликовано 7 ноября, 2015 · Жалоба В чем подвох? OTG_FS_DOEPCTL0.EPENA установлен? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 7 ноября, 2015 Опубликовано 7 ноября, 2015 · Жалоба OTG_FS_DOEPCTL0.EPENA установлен? Прерывание по RXFLVL у меня построено сейчас вот так: static void ISRH_RxFifoNonEmpty(void) { UINT32 status = OTG_FS->GRXSTSP; /* Get the Status from the top of the FIFO */ UINT8 ep_num = ((status & OTG_FS_GRXSTSP_EPNUM_MSK) >> OTG_FS_GRXSTSP_EPNUM_POS); INT data_len = ((status & OTG_FS_GRXSTSP_BCNT_MSK) >> OTG_FS_GRXSTSP_BCNT_POS); g_EP_Desc[0].data_len = data_len; UINT8 packet_status = ((status & OTG_FS_GRXSTSP_PKTSTS_MSK) >> OTG_FS_GRXSTSP_PKTSTS_POS); switch(packet_status) { case 0x01: /* Global OUT NAK (triggers an interrupt) */ break; case 0x02: /* OUT data packet received */ if(0 == ep_num) { USBD_CTRL_STATE usbd_state = USBD_DataOut(); /* Process the setup request parse */ if(USBD_CTRL_STAGE_DATA_IN == usbd_state) /* DATA_IN stage */ OTG_FS->DIEPEMPMSK |= (UINT32)1; /* Enable TX FIFO empy intr. from EP0 */ } break; case 0x03: /* OUT transfer completed (triggers an interrupt) */ break; case 0x04: /* SETUP transaction completed (triggers an interrupt) */ break; case 0x06: /* SETUP data packet received */ if(0 == ep_num) { USBD_CTRL_STATE usbd_state = USBD_Setup(); /* Process the setup request parse */ if(USBD_CTRL_STAGE_DATA_IN == usbd_state) /* DATA_IN stage */ OTG_FS->DIEPEMPMSK |= (UINT32)1; /* Enable TX FIFO empy intr. from EP0 */ } break; default: break; } } Функции верхнего уровня: USBD_Setup() и USBD_DataOut() для чтения из RX буфера используют одну и ту же функцию чтения: USBD_RESULT IUSBD_EP0_Read(P_UINT8 data, INT data_len, P_INT xfer) { if(data_len > g_EP_Desc[0].data_len) data_len = g_EP_Desc[0].data_len; g_EP_Desc[0].data_len = 0; EP_OUT_FIFO_SW_Get((void *)IUSBD_FIFO_BASE, (void *)data, data_len); /* Read data from FIFO */ OTG_FS->DOEPTSIZ0 = /* Setup transfer size for ready to receive */ OTG_FS_DOEPTSIZ0_XFRSIZ(USBD_CFG_DEVICE_EP0_SIZE * IUSBD_CFG_EP0_DOEPTSIZ_STUPCNT) | OTG_FS_DOEPTSIZ0_PKTCNT | OTG_FS_DOEPTSIZ0_STUPCNT(IUSBD_CFG_EP0_DOEPTSIZ_STUPCNT); OTG_FS->DOEPCTL0 |= (OTG_FS_DOEPCTL0_CNAK | OTG_FS_DOEPCTL0_EPENA); *xfer = data_len; return USBD_RES_OK; /* OK */ } Т.е. NAK и EPENA программируются сразу после вычитывания буфера. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 63 7 ноября, 2015 Опубликовано 7 ноября, 2015 · Жалоба Т.е. NAK и EPENA программируются сразу после вычитывания буфера. Так выходит, что до получения первого пакета EPENA не установлен? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 7 ноября, 2015 Опубликовано 7 ноября, 2015 · Жалоба Так выходит, что до получения первого пакета EPENA не установлен? Вот эта часть кода: OTG_FS->DOEPTSIZ0 = /* Setup transfer size for ready to receive */ OTG_FS_DOEPTSIZ0_XFRSIZ(USBD_CFG_DEVICE_EP0_SIZE * IUSBD_CFG_EP0_DOEPTSIZ_STUPCNT) | OTG_FS_DOEPTSIZ0_PKTCNT | OTG_FS_DOEPTSIZ0_STUPCNT(IUSBD_CFG_EP0_DOEPTSIZ_STUPCNT); OTG_FS->DOEPCTL0 |= (OTG_FS_DOEPCTL0_CNAK | OTG_FS_DOEPCTL0_EPENA); Так же исполняется по приходу прерывания USB Bus Reset. Так что точка всегда готова к приему пакетов. И, когда приходит прерывание о новом пакете, и это DATA OUT stage - количество данных в GRXSTSP верное - 7 байт. Только данные почему то не те, которые послал хост... В остальном все работает нормально. Данные по OUT BULK точке я еще принимать не пробовал. Пока хочу разобраться почему в буфере не то что передал хост. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 63 7 ноября, 2015 Опубликовано 7 ноября, 2015 · Жалоба Так же исполняется по приходу прерывания USB Bus Reset. Так что точка всегда готова к приему пакетов. EPENA сбрасывается при каждом SETUP'е, устанавливать надо непосредственно перед приемом пакета. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 7 ноября, 2015 Опубликовано 7 ноября, 2015 · Жалоба EPENA сбрасывается при каждом SETUP'е, устанавливать надо непосредственно перед приемом пакета.Не понял, что значит "устанавливать надо непосредственно перед приемом пакета". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 63 7 ноября, 2015 Опубликовано 7 ноября, 2015 · Жалоба Не понял, что значит "устанавливать надо непосредственно перед приемом пакета". Получили SETUP - узнали из него, что будет "продолжение" в виде OUT-транзакции - тут же на месте взвели EPENA. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 7 ноября, 2015 Опубликовано 7 ноября, 2015 · Жалоба Получили SETUP - узнали из него, что будет "продолжение" в виде OUT-транзакции - тут же на месте взвели EPENA. Но я вроде так и делаю. В функции IUSBD_EP0_Read получаю SETUP: Вычитываю данные из RX FIFO и тут же взвожу EPENA и CNAK Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 63 7 ноября, 2015 Опубликовано 7 ноября, 2015 · Жалоба Но я вроде так и делаю. В функции IUSBD_EP0_Read получаю SETUP: Вычитываю данные из RX FIFO и тут же взвожу EPENA и CNAK Перенесите обработку SETUP сюда: case 0x04: /* SETUP transaction completed (triggers an interrupt) */ Именно в этот момент EPENA и снимается. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 7 ноября, 2015 Опубликовано 7 ноября, 2015 · Жалоба Перенесите обработку SETUP сюда: case 0x04: /* SETUP transaction completed (triggers an interrupt) */ Именно в этот момент EPENA и снимается. Спасибо. Как всегда помогли быстро разобраться. :a14: :beer: Правда взвод точки я воткнул не в том месте кода, как Вы сказали, а в обработчике от OUT точки по флагу STUP (SETUP phase done) в регистре DOEPINT0. Перечитал даташит про EPENA в DOEPCTL0: Bit 31EPENA:Endpoint enable The application sets this bit to start transmitting data on endpoint 0. The core clears this bit before setting any ofthe following interrupts on this endpoint: – SETUP phase done – Endpoint disabled – Transfer completed Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 63 7 ноября, 2015 Опубликовано 7 ноября, 2015 · Жалоба Спасибо. Пожалуйста :) Правда, веселый контроллер USB у STM? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 7 ноября, 2015 Опубликовано 7 ноября, 2015 · Жалоба Правда взвод точки я воткнулНеа, не туда воткнул :) В общем сделал как советовали. Теперь код прерывания по RXFLVL выглядит вот так: static void ISRH_RxFifoNonEmpty(void) { UINT32 status = OTG_FS->GRXSTSP; /* Get the Status from the top of the FIFO */ UINT8 ep_num = ((status & OTG_FS_GRXSTSP_EPNUM_MSK) >> OTG_FS_GRXSTSP_EPNUM_POS); INT data_len = ((status & OTG_FS_GRXSTSP_BCNT_MSK) >> OTG_FS_GRXSTSP_BCNT_POS); g_EP_Desc[0].data_len = data_len; UINT8 packet_status = ((status & OTG_FS_GRXSTSP_PKTSTS_MSK) >> OTG_FS_GRXSTSP_PKTSTS_POS); switch(packet_status) { case 0x01: /* Global OUT NAK (triggers an interrupt) */ break; case 0x02: /* OUT data packet received */ if(0 == ep_num) { USBD_CTRL_STATE usbd_state = USBD_DataOut(); /* Process the setup request parse */ if(USBD_CTRL_STAGE_DATA_IN == usbd_state) /* DATA_IN stage */ OTG_FS->DIEPEMPMSK |= (UINT32)1; /* Enable TX FIFO empy intr. from EP0 */ } break; case 0x03: /* OUT transfer completed (triggers an interrupt) */ break; case 0x04: /* SETUP transaction completed (triggers an interrupt) */ if(0 == ep_num) { OTG_FS->DOEPTSIZ0 = /* Setup transfer size for ready to receive */ OTG_FS_DOEPTSIZ0_XFRSIZ(USBD_CFG_DEVICE_EP0_SIZE * IUSBD_CFG_EP0_DOEPTSIZ_STUPCNT) | OTG_FS_DOEPTSIZ0_PKTCNT | OTG_FS_DOEPTSIZ0_STUPCNT(IUSBD_CFG_EP0_DOEPTSIZ_STUPCNT); OTG_FS->DOEPCTL0 |= (OTG_FS_DOEPCTL0_CNAK | OTG_FS_DOEPCTL0_EPENA); } break; case 0x06: /* SETUP data packet received */ if(0 == ep_num) { USBD_CTRL_STATE usbd_state = USBD_Setup(); /* Process the setup request parse */ if(USBD_CTRL_STAGE_DATA_IN == usbd_state) /* DATA_IN stage */ OTG_FS->DIEPEMPMSK |= (UINT32)1; /* Enable TX FIFO empy intr. from EP0 */ } break; default: break; } } Из функции IUSBD_EP0_Read код разрешения точки вообще убрал Пожалуйста :) Правда, веселый контроллер USB у STM?Ага веселый, но изучать все равно нужно - тренд. Мне сейчас интересно посмотреть, какая будет производительность у это OTG_FS ядра. Вижу, что ни о каком двойном буферировании BULK точек в мануале речи не идет - надеюсь оно там есть на уровне ядра? Криво, конечно, что OUT буфер один общий и его нужно обязательно вычитывать сразу, но если прикрутить DMA, то, в принципе, сносно должно получится. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 63 7 ноября, 2015 Опубликовано 7 ноября, 2015 · Жалоба Мне сейчас интересно посмотреть, какая будет производительность у это OTG_FS ядра. Вижу, что ни о каком двойном буферировании BULK точек в мануале речи не идет - надеюсь оно там есть на уровне ядра? Уровень буферизации зависит от количества памяти, выделенной в FIFO на прием для точки: если выделить на два пакета максимального размера, то будет как раз двойная. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 7 ноября, 2015 Опубликовано 7 ноября, 2015 · Жалоба Уровень буферизации зависит от количества памяти, выделенной в FIFO на прием для точкиЭто то понятно. Памяти в буфере можно выделить даже на 4 размера конечной точки BULK, при чем в обе стороны. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться