|
|
  |
STM32 USB FS OTG |
|
|
|
Nov 7 2015, 18:54
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Цитата(aaarrr @ Nov 8 2015, 00:48)  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 программируются сразу после вычитывания буфера.
--------------------
|
|
|
|
|
Nov 7 2015, 19:08
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Цитата(aaarrr @ Nov 8 2015, 01:02)  Так выходит, что до получения первого пакета 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 точке я еще принимать не пробовал. Пока хочу разобраться почему в буфере не то что передал хост.
--------------------
|
|
|
|
|
Nov 7 2015, 19:55
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(prottoss @ Nov 7 2015, 22:51)  Но я вроде так и делаю. В функции IUSBD_EP0_Read получаю SETUP: Вычитываю данные из RX FIFO и тут же взвожу EPENA и CNAK Перенесите обработку SETUP сюда: Код case 0x04: /* SETUP transaction completed (triggers an interrupt) */ Именно в этот момент EPENA и снимается.
|
|
|
|
|
Nov 7 2015, 20:16
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Цитата(aaarrr @ Nov 8 2015, 01:55)  Перенесите обработку SETUP сюда: Код case 0x04: /* SETUP transaction completed (triggers an interrupt) */ Именно в этот момент EPENA и снимается. Спасибо. Как всегда помогли быстро разобраться. Правда взвод точки я воткнул не в том месте кода, как Вы сказали, а в обработчике от 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
--------------------
|
|
|
|
|
Nov 7 2015, 20:37
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Цитата(prottoss @ Nov 8 2015, 02:16)  Правда взвод точки я воткнул Неа, не туда воткнул  В общем сделал как советовали. Теперь код прерывания по 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 код разрешения точки вообще убрал Цитата(aaarrr @ Nov 8 2015, 02:28)  Пожалуйста  Правда, веселый контроллер USB у STM? Ага веселый, но изучать все равно нужно - тренд. Мне сейчас интересно посмотреть, какая будет производительность у это OTG_FS ядра. Вижу, что ни о каком двойном буферировании BULK точек в мануале речи не идет - надеюсь оно там есть на уровне ядра? Криво, конечно, что OUT буфер один общий и его нужно обязательно вычитывать сразу, но если прикрутить DMA, то, в принципе, сносно должно получится.
--------------------
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|