Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

STM32 и аппаратный модуль USB

Пн дек 26, 2011 11:14:57

Всем доброе утро!
Стараюсь по возможности не обращаться за помощью, но в этот раз все совсем печально, и мое терпение и силы на исходе. В данный момент разбираюсь с USB микроконтроллера STM32L151 (то же самое, в принципе, что и в мэйнстримовой линейке STM32Fxx). Возникли проблемы с энумерацией.
Итак, по сути. Аппаратно: в линии DP и DM последовательно включил резисторы на 20 Ом. Внешним подтягивающим резистором не пользуюсь, просто при инициализации включаю внутреннюю подтяжку на DP.
Программу писал без использования прерываний, в бесконечном цикле мониторю состояние регистра ISTR, и пляшу исходя из этого.
Путем многочисленных экспериментов удалось установить суть происходящего: 1. Подключаю шнурок к разъему USB своего ноутбука. Хост (точнее, хаб) определяет подключение, дает RESET. Сбрасываюсь. Настраиваю нулевую конечную точку (тип Control, указываю адреса RX и TX-буферов, адрес конечной точки, разрешаю прием). 2. Определяю приход SETUP-пакета, читаю его. По содержимому полей bmRequest и bRequest узнаю, что имеет место запрос GET_DESCRIPTOR, вызываю функцию GetDescriptor (которая определяет тип запрашиваемого дескриптора, и соответствующим образом обрабатывает ситуацию - код чуть ниже). По содержимому старшего байта поля wValue определяю, что хост просит дескриптор устройства (GET_DEVICE_DESCRIPTOR). Полностью содержимое SETUP-пакета имеет вид: 0x80,0x06,0x00,0x01,0x00,0x00,0x40,0x00.
Пытаюсь отправить дескриптор устройства, однако не происходит совершенно ничего. Хост еще раз дает сброс, и ситуация повторяется аналогичным образом. Пощупал линию осциллографом - за все время от включения контроллера и до момента, когда хост дает повторный сброс, появляется пять одинаковых посылок (подозреваю, что это тот самый пакет SETUP). Контроллер же почему-то не отправляет ровным счетом ничего, так получается.. Хотя бит CTR_TX в регистре нулевой конечной точки EP0R устанавливается (это якобы свидетельствует об успешной передаче - хост ответил ACK-"рукопожатием").
Уже совершенно ничего не могу понять - где я допускаю косяк..
На всякий случай (вдруг у кого будет охота глянуть) привожу код обработки запроса GET_DESCRIPTOR.
Код:
void GetDescriptor(void)
{
  u8 Request_Desc;
  BYTE data_to_transfer;
  uint16_t wLength;
  unsigned char zlp;
  BYTE *pbuffer;
  zlp=FALSE;
 
  Request_Desc = Cam_Bufer[3];    //определяем, какой дескриптор просит хост (в Cam_Bufer[3] - старший байт поля wValue)
  switch (Request_Desc)
    {
      case DEVICE:                       
        { 
          data_to_transfer = sizeof(usb_device_descriptor);
          pbuffer=&(usb_device_descriptor.bLength);
          break;
        }
      case CONFIGURATION:
        {
          data_to_transfer = sizeof(usb_configuration);
          pbuffer = &(usb_configuration.cfg.bLength);
          break;
        }
    }
 
  wLength=ToWord(Cam_Bufer[7],Cam_Bufer[6]);         //объединяем в слово байты поля wLength

  if (wLength>data_to_transfer)                                    //если длина пакета хоста больше размера дескриптора
    {   
        if ((data_to_transfer % EP_CONTROL_LENGTH) == 0)    //и если длина дескриптора делится на макс. размер пакета КТ
          {zlp = TRUE;}                                                          //то нужно будет послать пакет данных нулевой длины
        else
          {zlp = FALSE;}                                                        // если нет, то пакет нулевой длины не потребуется
    }
  else
    {data_to_transfer=wLength;}
 
 while (data_to_transfer>EP_CONTROL_LENGTH)                  //пока объем данных для пересылки больше пакета нулевой КТ
    {
      UserToPMABufferCopy(pbuffer,_GetEPTxAddr(ENDP0),EP_CONTROL_LENGTH);  //копируем в PMA 8 байт дескриптора
      SetEPTxCount(ENDP0,EP_CONTROL_LENGTH);                                              //устанавливаем счетчик для отправки=8 байт
      SetEPTxValid(ENDP0);                                                                                //разрешаем передачу КТ
      pbuffer+=EP_CONTROL_LENGTH;                                                                //смещаем указатель на 8
      data_to_transfer-=EP_CONTROL_LENGTH;                                                   //уменьшаем размер данных к передаче на 8
     
      while (!(USB->USB_EP0R&USB_EP0R_CTR_TX)) {}               //ждем, пока не пройдет передача
      USB->USB_EP0R &= ~USB_EP0R_CTR_TX;                          //чистим бит успешной передачи
    }
        //отсылаем остаточный пакет данных     

      UserToPMABufferCopy(pbuffer,_GetEPTxAddr(ENDP0),EP_CONTROL_LENGTH);
      SetEPTxCount(ENDP0,EP_CONTROL_LENGTH);
      SetEPTxValid(ENDP0);
      data_to_transfer=0;
      while (!(USB->USB_EP0R&USB_EP0R_CTR_TX)) {}
      USB->USB_EP0R &= ~USB_EP0R_CTR_TX;
     

   //если требуется пакет данных нулевой длины, то отправляем его
    if (zlp==TRUE)
    {
      Send0LengthData();
      while (!(USB->USB_EP0R&USB_EP0R_CTR_TX)){}
      USB->USB_EP0R &= ~USB_EP0R_CTR_TX;
    }
    //разрешаем прием нулевой КТ
    SetEPRxCount(ENDP0,8);
    SetEPRxStatus(ENDP0,EP_RX_VALID);
return;   
}


Все функции, использованные мной - из стандартной библиотеки от ST, грешить на неработоспособность их не приходится. Грешить приходится на собственные кривые ручонки.
Так вот, если кто-нибудь обратил внимание на то, что я что-то делаю неподобающим образом, буду благодарен за комментарии.

Re: STM32 и аппаратный модуль USB

Ср дек 28, 2011 11:35:37

В общем, проблема решена, и искать причины ее возникновения пришлось не в программной, а в аппаратной части. Мысль сия посетила меня после того, как залил в контроллер скомпилированный под свой камень один из готовых проектов, кои в количестве нескольких штук любезно предоставляет SGS Thomson Microelectronics вместе с библиотекой USB FS Library.
Результат оказался тем же, что и в случае с моим проектом - "устройство USB не опознано". А гадил кварцевый резонатор, после замены которого устройство распрекраснейшим образом определилось системой. Для меня, правда, так и осталось загадкой - каким же образом контроллер умудрялся получать запросы от хоста, но я решил все же не ломать особо над этим голову (поразмыслю на досуге как-нибудь, когда-нибудь).
И еще пришла в голову мысль не бороться с ветряными мельницами и использовать готовую библиотеку от производителя в своих проектах. Ибо теорию работы протокола USB я уже изучил вдоль и поперек, а изобретать лисапед - занятие весьма неблагодарное.

Re: STM32 и аппаратный модуль USB

Ср дек 28, 2011 11:57:18

SubDia писал(а):И еще пришла в голову мысль не бороться с ветряными мельницами и использовать готовую библиотеку от производителя в своих проектах.

С этого и надо было начинать :))) :)))
Только с осторожностью - на первую ошибку я там наткнулся на второй день разбирательств.

Скорость не мерял, но субъективно работает как то не шустро. При том, что использую выделенный на ендпойнт аппаратный FIFO и DMA.

USB очень чувствительно к тактовке. Про RC сразу можно забыть, про 99% керамических резонаторов тоже. Только кварцы.

Re: STM32 и аппаратный модуль USB

Ср дек 28, 2011 12:14:18

Satyr писал(а):Только с осторожностью - на первую ошибку я там наткнулся на второй день разбирательств.

Позвольте полюбопытствовать - что за ошибка?
Satyr писал(а):USB очень чувствительно к тактовке. Про RC сразу можно забыть, про 99% керамических резонаторов тоже. Только кварцы.

Да, я уж ощутил это на себе в полной мере :)))
Содрал у STM на сайте занимательную штуку для L15x - Clock Configuration Tool зовется. О ней Вы наверняка знаете. Одно в ней плохо - при превышениях любых допустимых значений (VCO, HCLK и т.д.) выдает ошибку-предупреждение с рекомендациями, а вот если ставишь галку "Require 48 MHz for USB Clock", и при этом указываешь источник PLL - HSI, не ругается, и спокойно генерирует файл system.h.
Это уж в даташите, когда читал, вглядываясь подробно в каждую букву, обнаружил лаконичное упоминание о том, что при необходимости использовать USB-периферию в проекте, использовать HSI низзя. =)

Re: STM32 и аппаратный модуль USB

Ср дек 28, 2011 12:21:42

SubDia писал(а):
Satyr писал(а):Только с осторожностью - на первую ошибку я там наткнулся на второй день разбирательств.

Позвольте полюбопытствовать - что за ошибка?


В исходниках такую чтуку ищи
/*ToDo : handle more than one single MPS size packet */

Правда оно только при использовании DMA всплывает.
Длина принятых данных кривая, если длина принятых данных больше длины ендпойнта

на скору руку решение
// pdev->dev.out_ep[1].xfer_count = pdev->dev.out_ep[1].maxpacket - deptsiz.b.xfersize;
int pktcnt = (pdev->dev.out_ep[1].xfer_len - 1 + pdev->dev.out_ep[1].maxpacket) / pdev->dev.out_ep[1].maxpacket;
pdev->dev.out_ep[1].xfer_count = pdev->dev.out_ep[1].maxpacket * pktcnt - deptsiz.b.xfersize;

С DCD_EP_PrepareRx() неочевидный прикол, что принимает не сколько аргументом просишь, а оно же округленное вверх до длины ендпойнта. С точки зрения USB закономерно, с точки зрения описания API - как то не особо.

Вроде еще чтото гдето правил, не помню.

И композитные девайсы библиотека штатно не поддерживает. У меня MSC и CCID в одном флаконе -))

Содрал у STM на сайте занимательную штуку для L15x - Clock Configuration Tool зовется. О ней Вы наверняка знаете.

Видел, но мне проще руками быстренько настроить под себя.

Re: STM32 и аппаратный модуль USB

Пт янв 06, 2012 12:08:56

Satyr, благодарю за предостережение от подводных камней. И прошу прощения за поздний ответ. :)

Кстати, для тех, кто интересуется, или будет интересоваться темой, и возможно прочтет это сообщение.
Нашел интересную утилитку, входящую в состав WinDriver USB. Штука называется usb_diag, консольное приложение, позволяющее осуществлять обмен данными с USB-устройством (мне в процессе отладки весьма и весьма пригодилась).

Изображение

Изображение

Изображение

Re: STM32 и аппаратный модуль USB

Пт янв 06, 2012 17:28:33

Есть порт usblib - тоже дает "без драйверов" общаться с USB девайсом.
Все что на или около Junko WinDriver - глюк нечеловеческий.

А есть еще меготема "Compuware DriverStudio" - основу драйвера делает сама по шаблону + дескриптору, получаемому с USB устройства.
Остается только описать свои IOCtrl вызовы и в них сунуть/вынуть в пайп и всё. Без костылей.

Ну и сниферов всяких полно, чтоб посмотреть, что происходит. Я пользовал простенький Snoopy - хватало.

Re: STM32 и аппаратный модуль USB

Пт янв 06, 2012 17:36:43

Satyr писал(а):Все что на или около Junko WinDriver - глюк нечеловеческий.

Да, слыхал такие отзывы о WinDriver'е. Однако решил пощупать своими руками все же. :)
Кстати говоря, первый глюк дал о себе знать сразу же. В самом Juno WinDriver при попытке того же самого "послушать" канал (listen to pipe) не происходило ровным счетом ничего - чистое и белое окошко. Уж было решил, что все.. Начал ковырять программу МК - да нет же, все правильно. И только когда запустил этот самый usb_diag, увидел в режиме чтения бегущие данные от устройства. Так что наше с WinDriver совместное будущее теперь видится мне весьма и весьма бесперспективным. =)))
Спасибо за подсказку насчет "Compuware DriverStudio", поковыряю. Конечно, кухню хочу изучить изнутри, но пока что даже слабенько себе представляю с какой стороны подходить. На данный момент только и успел, что учебников накачать.)

Re: STM32 и аппаратный модуль USB

Ср июл 04, 2012 13:08:44

SubDia, Satyr, может тогда сделаете статейку по USB? Я пока на стадии курения документации USB in a NutShell, посмотрев примеры от STM (там правда много чего понапихано, простых нету), понял что тихо начинает протекать крыша. :)

Правда судя по написанному на форумах, блогах, при знакомстве даже с аппаратно реализованным USB взять его совсем не простая задача. Еще бы, один из самых сложных протоколов.
Есть конечно выход - FT232, но это как-то не спортивно при наличии USB на борту, да и стоимость последней как 2-3 средних камня STM32

Re: STM32 и аппаратный модуль USB

Чт июл 05, 2012 03:01:47

Статейка-то маленькой не получится. Что в ней писать? Пересказывать стандарт USB 2.0? :)
Я сейчас тружусь над одним HID-устройством, и даже, вполне возможно, по нему накатаю статью, но сразу оговорюсь, что часть, касающаяся обмена по USB, создана на базе примера JoystickMouse от STM (библиотека USB FS для МК STM32L151).

Re: STM32 и аппаратный модуль USB

Сб июл 07, 2012 20:37:56

Примеров полно что с библиотеками СТшными, что в комплекте с IARом.
Что не понятно - спрашивайте.

Re: STM32 и аппаратный модуль USB

Вс ноя 11, 2012 11:05:33

есть stm32f407 которая должна общаться с компьютером..
FT232 и различные USB-UART использовать не хочу (в чипе есть железный USB)

что мне нужно чтобы организовать двустороннюю передачу данных устройства\ПК ?
подскажите простой способ, где что почитать...?

еще интересует есть ли например в Винде какое нить стандартное устройство чтобы не приходилось дополнительно ставить драйвера ?
может есть способ получать данные как например это происходит при подключении мыши (ведь какую не воткни - сразу работает !)

возможно вопросы немного сумбурны - только начал читать про usb.. везде нахожу слишком сложные примеры :-(

Re: STM32 и аппаратный модуль USB

Вс ноя 11, 2012 13:41:46

ВитГо писал(а):есть stm32f407 которая должна общаться с компьютером..
FT232 и различные USB-UART использовать не хочу (в чипе есть железный USB)

Естественно. На кой костыли, если в МК есть полностью достаточный USB контроллер ? Тупо только разьем припаять.

что мне нужно чтобы организовать двустороннюю передачу данных устройства\ПК ?
подскажите простой способ, где что почитать...?

На гугле, как вариант.

еще интересует есть ли например в Винде какое нить стандартное устройство чтобы не приходилось дополнительно ставить драйвера ?
может есть способ получать данные как например это происходит при подключении мыши (ведь какую не воткни - сразу работает !)

Надо реализовать USB устройство стандартного класса. Поскольку они производителе независимые, то и драйвер для всех одинаковый стандартный.
Это MSC, CDC, HID, RNDIS (родной только в виндах. В XP нужен inf файл), CCID (в виндах inf не нужен. в линуксе нужна установка доп. модулей).

Если скорости < 64kb/s достаточно, то проще HID
Если без ограничения, но с настройкой в программе (ручной выбор порта), то CDC
Если с автонастройкой в большинстве стандартных ситуаций (но особым гемором в редких нестандартных случаях -)) ) - CCID/RNDIS

Re: STM32 и аппаратный модуль USB

Сб июл 06, 2013 22:31:34

Есть у когонибудь готовая программа работы c USB?чтобы посмотреть и переделать под свой.
Самая простая передача байта и прием.
Ответить