Top.Mail.Ru
Короче, я не знаю, что дальше делать. - No Xians Here — ЖЖ
? ?
 

Короче, я не знаю, что дальше делать.

About Уничтожить всех уродов

Previous Entry Короче, я не знаю, что дальше делать. 8 апр, 2015 @ 20:26 Next Entry
Переписал код ВЕСЬ заново, используя заведомо рабочий проект как основу.

Не работает.

Энумерация идёт почти прекрасно (за исключением того, что первый раз "пробный" запрос дескриптора виснет, если размер буфера меньше, чем размер оного дескриптора - сразу сброс по шине проходит). Но если размер буфера поставить больше - хотя бы 32 байта - тогда первый запрос проходит нормально, затем ожидаемый сброс, команда установки адреса (отрабатывается так, как надо - адрес меняется после отправки подтверждения) и... снова сброс, и всё начинается заново. И это если к компу подключить. А если подключить дивайс к хабу, то он даже адрес не устанавливает - пробный запрос, сброс, пробный запрос, сброс, останов. Или устанавливает, но следующий нормальный запрос дескриптора не присылает.

Я перепробовал все мыслимые варианты и близок к помешательству.

Видимо, придётся таки использовать библиотеку от ST - она почему-то работает, но ужасно громоздкая... :(
Оставить комментарий
[User Picture Icon]
From:mbr
Date:Апрель, 8, 2015 17:41 (UTC)
(Link)
Неверно ставится адрес устройства. Либо не в том месте, либо не так.

Размер буфера нужно ставить в размер эндпоинта. Сразу. Т.е., если в дескрипторе 64 байта, значит 64.

Еще раз повторюсь, что приложение кода гарантированно решит проблему.
[User Picture Icon]
From:kincajou
Date:Апрель, 8, 2015 18:36 (UTC)
(Link)
да чего код, это тот же самый код и есть, от dfu-flasher. Только причёсаный немного - я свои макросы использую там, гд можно обойтись без вызовов функций (даже если это инлайн-функции), типа где маски устанавливаются и всё такое. А в дескриптор я сразу прописал задефайненое значение - если я его меняю, дескриптор тоже изменяется (и я это вижу в отладке).


Убил полдня на удивительное явление - когда проходит первый резет по шине, регистр EP0R сразу же обнуляется. То есть, я вроде ещё прописываю в него какие-то там поля, а он всё равно обнулёН, потому что сброс шины.
[User Picture Icon]
From:mbr
Date:Апрель, 9, 2015 06:55 (UTC)
(Link)
Код от STM32L0 - на первый взгляд это тоже самое, но могут быть подводные камни.

Инлайн функции всегда предпочтительнее макросов. Встраиваемость инлайн-функций регулируется компилятором, плюс, и это самое важное - значительно уменьшается вероятность ошибки. Исторически дефайны используются для определения констант и битовых сдвигов, не более того.
[User Picture Icon]
From:kincajou
Date:Апрель, 9, 2015 07:01 (UTC)
(Link)
Разумеется, и поэтому всегда можно обернуть макрос в инлайн-функцию (как в либе от ST, кстати, и сделано - почти каждый макрос имеет "обёрнутый" вариант). Но пока я не нашёл ошибок, связанных именно с этим - биты устанавливаются и сбрасываются макросами именно так, как должны
[User Picture Icon]
From:mbr
Date:Апрель, 9, 2015 07:04 (UTC)
(Link)
Я написал, как правильно, а не как работает :) Работает в обоих случаях.
[User Picture Icon]
From:kincajou
Date:Апрель, 9, 2015 07:20 (UTC)
(Link)
а отличий в USB-модуле я пока не нашёл. Если они и есть, то, похоже, в каких-то количественных показателях
[User Picture Icon]
From:kincajou
Date:Апрель, 8, 2015 18:50 (UTC)
(Link)
адрес - какой пришёл, такой и ставлю. И тогда, когда пакет, подтверждающий запрос SET_ADRESS, точно отправился - вот был запрос, вот ушёл нулевой длины пакет, вот я ставлю адрес, вот хобана! снова резет шины! вот тебе мочало, начинай сначала. Но это с хабом. А комп после установки адреса присылает запрос на дескриптор, спокойно читает три кусочка (пропихиваю 18 байт через буфер объёмом 8 байт - 8, 8 и 2), присылает свой STATUS и ... хобана! резет шины!


меня эта разжница в алгоритмах работы очень удивляет. Мало того, комп фигачит запросами с заметно бОльшей скоростью, чем хаб. Неужели стандарт не оговаривает продолжительность пауз и общее количество запросов перед констатацией фейла?

Edited at 2015-04-08 18:51 (UTC)
[User Picture Icon]
From:mbr
Date:Апрель, 9, 2015 05:34 (UTC)
(Link)
Буфер 8 байт?! EP0 size обычно 64, вот 64 и надо гонять в одном пакете. Неполный пакет - признак конца передачи.
[User Picture Icon]
From:kincajou
Date:Апрель, 9, 2015 06:21 (UTC)
(Link)
дык если в дескрипторе прописан размер 8 байт, то посылка длиной в те же 8 байт будет считаться полной, не так ли?

кроме того, в массе примеров именно такой размер и установлен. Опять же, выделять под контрольную точку аж 64 байта (на самом деле, все 128 - под приём ведь тоже) из всего-то 512 - это, имхо, роскошь
[User Picture Icon]
From:mbr
Date:Апрель, 9, 2015 06:52 (UTC)
(Link)
Так исторически сложилось, что у FS девайсов ep0 размер, в основном, 64 байта. Я бы не рекомендовал делать меньше, стек хоста не факт что отработает корректно в этом случае.
[User Picture Icon]
From:kincajou
Date:Апрель, 9, 2015 06:54 (UTC)
(Link)
я, разумеется, этот вариант тоже проверил - устаноаил размер 64, убедился, что адреса в BTABLE правильные,... от компа пришёл запрос на дескриптор 0F с длиной данных F4 (не нашёл такое в стандарте), а хаб по-прежнему полчит после установки адреса. Установил, помолчал, сброс шины. Я проверяю - в регистре DADDR прописан (DADDR_EF | Address), а установка адреса делается так:
if (USB->EPR[EP_ID] & USB_EP0R_CTR_TX) /* что-то было передано */
{
	USB_EP_t *ep = &CommonData.EP_In[EP_ID];
	EP_CLEAR_CTR_TX(EP_ID);

	if (CommonData.USBAddress && (GET_COUNT_TX(EP_ID) == 0))
	/* Адрес был прислан ранее (там не нуль), а количество переданных данных - нуль
	 * Это значит, был передан подтверждающий пакет STATUS,
	 * а адрес мы ранее уже запомнили и сейчас самое время его УСТАНОВИТЬ! */
	{
		printf ("Applying new address %02X\n\r", CommonData.USBAddress);
		USB->DADDR = (USB_DADDR_EF | (CommonData.USBAddress & 0x7F)); 
		/* с этого момента мы Василий */
		CommonData.USBAddress = 0; /* а вдруг захотим установить другой, мало ли */
		CommonData.USBState = USBD_STATE_ADDRESSED;
		return;
	}
....
[User Picture Icon]
From:mbr
Date:Апрель, 9, 2015 07:30 (UTC)
(Link)
> от компа пришёл запрос на дескриптор 0F с длиной данных F4

О это хорошее начало. Это значит от компа пришел мусор. Я бы все-таки смотрел в сторону буферов. Выравнивание всех данных нормальное - 4?
[User Picture Icon]
From:kincajou
Date:Апрель, 8, 2015 18:54 (UTC)
(Link)
ещё что смущает: STшная либа перед началом разбора пакета смотрит на флаг DIR - и в зависимости от его значения обрабатывает или IN, или OUT со STATUSом. Но я вижу, что DIR всё время равен нулю и не меняется...
[User Picture Icon]
From:mbr
Date:Апрель, 9, 2015 05:35 (UTC)
(Link)
Это разбирается на уровне стека.
[User Picture Icon]
From:kincajou
Date:Апрель, 9, 2015 06:24 (UTC)
(Link)
в смысле, на каком именно уровне? аппаратно где-то?
Я имею в виду, что у них код обработчика прерывания CTR сначала смотрит на DIR и уже потом решает, что там за пакет был:
while (((wIstr = _GetISTR()) & ISTR_CTR) != 0)
  {
    /* extract highest priority endpoint number */
    EPindex = (uint8_t)(wIstr & ISTR_EP_ID);
    if (EPindex == 0)
    {
      /* Decode and service control endpoint interrupt */
      /* calling related service routine */
      /* (Setup0_Process, In0_Process, Out0_Process) */

      /* save RX & TX status */
      /* and set both to NAK */
      
	    SaveRState = _GetENDPOINT(ENDP0);
	    SaveTState = SaveRState & EPTX_STAT;
	    SaveRState &=  EPRX_STAT;	

	    _SetEPRxTxStatus(ENDP0,EP_RX_NAK,EP_TX_NAK);

      /* DIR bit = origin of the interrupt */

      if ((wIstr & ISTR_DIR) == 0)
      {
        /* DIR = 0 */

        /* DIR = 0      => IN  int */
        /* DIR = 0 implies that (EP_CTR_TX = 1) always  */

        _ClearEP_CTR_TX(ENDP0);
        In0_Process();

           /* before terminate set Tx & Rx status */

            _SetEPRxTxStatus(ENDP0,SaveRState,SaveTState);
		  return;
      }
      else
      {
        /* DIR = 1 */

        /* DIR = 1 & CTR_RX       => SETUP or OUT int */
        /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */

        wEPVal = _GetENDPOINT(ENDP0);
        
        if ((wEPVal &EP_SETUP) != 0)
        {
          _ClearEP_CTR_RX(ENDP0); /* SETUP bit kept frozen while CTR_RX = 1 */
          Setup0_Process();
          /* before terminate set Tx & Rx status */

		      _SetEPRxTxStatus(ENDP0,SaveRState,SaveTState);
          return;
        }

        else if ((wEPVal & EP_CTR_RX) != 0)
        {
          _ClearEP_CTR_RX(ENDP0);
          Out0_Process();
          /* before terminate set Tx & Rx status */
     
		     _SetEPRxTxStatus(ENDP0,SaveRState,SaveTState);
          return;
        }
      }
    }/* if(EPindex == 0) */
    else
    {
      /* Decode and service non control endpoints interrupt  */

      /* process related endpoint register */
      wEPVal = _GetENDPOINT(EPindex);
      if ((wEPVal & EP_CTR_RX) != 0)
      {
        /* clear int flag */
        _ClearEP_CTR_RX(EPindex);

        /* call OUT service function */
        (*pEpInt_OUT[EPindex-1])();

      } /* if((wEPVal & EP_CTR_RX) */

      if ((wEPVal & EP_CTR_TX) != 0)
      {
        /* clear int flag */
        _ClearEP_CTR_TX(EPindex);

        /* call IN service function */
        (*pEpInt_IN[EPindex-1])();
      } /* if((wEPVal & EP_CTR_TX) != 0) */

    }/* if(EPindex == 0) else */

  }/* while(...) */


А я ни разу не видел установленный DIR, всегда сброшен

Edited at 2015-04-09 06:25 (UTC)
(Оставить комментарий)
Top of Page Разработано LiveJournal.com