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

Re: STM32 и USB (практика)

Вт май 31, 2016 19:38:50

...Передавать надо ровно столько данных, сколько просит хост, по крайней мере не длиннее.

да-да, я не так выразился.
Хост в запросе говорит что максимальная длина пакета 0x40 байт, допустимо отправить не больше этого значения.

На любой косяк хост "обижается". Вы должны четко соблюдать протокол. Описание дескрипторов, их длина. Очередность передачи и т.д. Если хост требует что-то сделать, но не требуются данные. Вы должны помахать в ответ ZLP. Например пришла команда установить адрес. Вы отвечаете ZLP, как от безадресного устройства, затем дальше все должно работать по адресу. Отправили дескриптор хосту, если хост его съест , то он отправит zlp.


Ну да, это понятно что чуть что и хост пошлет кривое устройство куда подальше. Буду дальше искать косяк.

На MSDN неплохо разрисовано.
MSDN пример обмена

Re: STM32 и USB (практика)

Ср июн 01, 2016 15:25:36

Есть соображения почему не попадаю в прерывание по отправке. Может быть дело в том, что хост отвечает NAK или STALL. Тогда флаг CTR_TX не выставляется и прерывание не срабатывает. Но вот как узнать чем ответил хост?

Re: STM32 и USB (практика)

Ср июн 01, 2016 18:29:03

Radist_M писал(а):В Буфере передатчика лежит заготовленный дескриптор (заранее положил туда), тогда я выставляю
Вы в буфер его правильно положили? Учли что 2 и 3 байты недоступны в 32 ом слове?

Re: STM32 и USB (практика)

Ср июн 01, 2016 20:48:54

Z_h_e писал(а): Вы в буфер его правильно положили? Учли что 2 и 3 байты недоступны в 32 ом слове?

Да, там все верно. Смотрел в Memory watch - 2 и 3 байт 32-битного слова не используются. Сейчас под рукой нету функции, которая заполняет буферную память на основе исходного массива (в смысле не могу показать).
Думаю может дескриптор не корректный. Хотя, вряд ли хост сразу сообразит, что дескриптор не корректный/

Re: STM32 и USB (практика)

Чт июн 02, 2016 05:41:04

Сообразит сообразит. Например, когда я ставил в дескрипторе устройства версию 2.0 и размер конфиг пакета отличный от 0x40, то хосту он не нравился. Но в любом случае если Вы отправили успешно данные, пускай даже с кривым дескриптором, флаг должен установится.

Re: STM32 и USB (практика)

Чт июн 02, 2016 08:28:04

Вот и я о том. Флаг выставляется только если попробовать передать 0 байт - COUNT_TX = 0. В случае COUNT_TX = 0x12 (18 байт) тишина.
Грешил на то что ноги неверно настроил, но в моем F103 вроде не нужно особым образом настраивать ноги. При включении USB ноги конфигурируются автоматически.

Re: STM32 и USB (практика)

Сб июн 04, 2016 11:22:14

Наше одну хрень при использование отладчика. Если попытаться посмотреть память в отладчике по адресу, то показывает всякую фигню, но если записать память в переменную, то в отладчике начинают отображаться нормальные значения.
Может кому поможет :) .

Re: STM32 и USB (практика)

Сб июн 04, 2016 15:48:03

Поправил код. Теперь проблема такая: не смотря на строчку USB->EP0R |= USB_EP_TX_NAK;, значение все равно сбрасывается в 0 (такая же фигня, если пытаться установить галочку в отладчике).
Также не приходит прерывание по CTR. Пол дня уже голову ломаю, вроде все выставил как положено, но работать никак не хочет :dont_know:

Спойлер
Код:
#include "stm32f303xc.h"

#define USB_MAX_PACKET0 ((uint16_t) 0x02)
//uint32_t test1 = 0x00000000;
uint32_t BTableOffset = 0x00000000; // указываем значение BTABLE

void MyUSBinit(void)
{

   uint32_t temp2;
   
/*Тактируем ядро*/   
   //RCC->CR |= RCC_CR_HSION; //Включить генератор HSI
   //RCC->CR &= ~RCC_CR_HSEON;
   RCC->CFGR &= ~RCC_CFGR_SW; //Очистка битов выбора источника тактового сигнала
   RCC->CR |= RCC_CR_HSEON;
   
//   FLASH->ACR |= FLASH_ACR_HLFCYA;
  FLASH->ACR |= FLASH_ACR_LATENCY_1;
  FLASH->ACR |= FLASH_ACR_PRFTBE;
   while((FLASH->ACR & FLASH_ACR_PRFTBS)==0) {}
   
  while((RCC->CR & RCC_CR_HSERDY)==0) {} //Ожидание готовности HSE
 
   RCC->CFGR |= RCC_CFGR_PLLSRC; //Источником сигнала для PLL выбран HSE (внешний - кварц на 8 МГц)
  RCC->CR &= ~RCC_CR_PLLON; //Отключить генератор PLL
  RCC->CFGR &= ~RCC_CFGR_PLLMUL; //Очистить PLLMULL
  RCC->CFGR |= RCC_CFGR_PLLMUL_0 | RCC_CFGR_PLLMUL_1 | RCC_CFGR_PLLMUL_2; //Коефициент умножения 9  (будет 72 МГЦ)
  RCC->CFGR |= RCC_CFGR_PPRE1_2;
   RCC->CR |= RCC_CR_PLLON; //Включить генератор PLL
  while((RCC->CR & RCC_CR_PLLRDY)==0) {} //Ожидание готовности PLL
   

      
 
  //Переключиться на тактирование от PLL
    //
   RCC->CFGR |= RCC_CFGR_SW_1 ; //Выбрать источником тактового сигнала PLL
      
  while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_1) {} //Ожидание переключения на PLL
   
/*Тактируем периферию*/      
   RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOEEN; // Включаем тактирование портов А и Е
   RCC->CFGR &= ~RCC_CFGR_USBPRE; // Настраиваем частоту USB (= частота ядра / 1.5)
   RCC->APB1ENR |=   RCC_APB1ENR_USBEN; // Включаем тактирование USB от шины APB1
   RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; // Включаем тактирование SYSCFG (хз что это, но так надо :) )

      /*----------*/
   
/*Настраиваем Порт А*/      
  GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR11 | GPIO_OSPEEDER_OSPEEDR12; // Скорость 50 МГц
   GPIOA->MODER |= GPIO_MODER_MODER11_1 | GPIO_MODER_MODER12_1; // Режим альтернативной функции (для USB)
   //GPIOA->OTYPER = 0x00000000;
   //GPIOA->PUPDR |= GPIO_PUPDR_PUPDR12_0;
   GPIOA->AFR[1] |= 0x000EE000; // Номер и пины альтернативной фунции (у нас пины 11 и 12 для альтернативной функции номер 14 - USB)
   
/*Настраиваем Порт Е*/         
  GPIOE->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR8 | GPIO_OSPEEDER_OSPEEDR9 | GPIO_OSPEEDER_OSPEEDR10 |
                     GPIO_OSPEEDER_OSPEEDR11 | GPIO_OSPEEDER_OSPEEDR12 | GPIO_OSPEEDER_OSPEEDR13 |
                      GPIO_OSPEEDER_OSPEEDR14 | GPIO_OSPEEDER_OSPEEDR15; // Скорость для указанных пинов 50 МГц
   GPIOE->MODER |= GPIO_MODER_MODER8_0 | GPIO_MODER_MODER9_0 | GPIO_MODER_MODER10_0 |
                   GPIO_MODER_MODER11_0 | GPIO_MODER_MODER12_0 | GPIO_MODER_MODER13_0 |
                   GPIO_MODER_MODER14_0 | GPIO_MODER_MODER15_0; // Указанные пины на выход
   //GPIOE->OTYPER = 0x00000000;
   //GPIOE->PUPDR = 0x00000000;
   //GPIOE->AFR[1] |= 0x00000000;
   
      /*----------*/
                                 
  EXTI->RTSR |= EXTI_RTSR_TR18; // внешнее прерывание №18 (USBWakeUp) по возрастающему фронту
  EXTI->IMR |= EXTI_IMR_MR18; // Включаем прерывание по пинам
  //EXTI->EMR |= EXTI_EMR_MR18; // Включаем прерывание по событию (USBWakeUp - по обнаружению устройства)
      
      /*----------*/
         
   NVIC_EnableIRQ(USB_LP_CAN_RX0_IRQn);
  NVIC_SetPriority(USB_LP_CAN_RX0_IRQn, 8);   
   NVIC_EnableIRQ(USBWakeUp_IRQn); //   Разрешаем глобально прерывание USBWakeUp
  //NVIC_SetPriority(USBWakeUp_IRQn, 3);   // Приоритет прерывания (не могу определится для USB)
      
      /*----------*/                                                      

//здесь нужно включаить бит подтяжки резистора (но на плате STM32F3Discovery он припаян)

USB->CNTR = 0x3;
USB->CNTR &= ~USB_CNTR_PDWN;             

for ( temp2=10000000; temp2 != 0; temp2--);

USB->CNTR &= ~USB_CNTR_FRES;
//USB->ISTR = 0;
USB->CNTR |= USB_CNTR_RESETM | USB_CNTR_CTRM;

  }

void USB_LP_CAN_RX0_IRQHandler(void)
{
//uint8_t tmp = 0;   

   
if (USB->ISTR & USB_ISTR_CTR)
{
   USB->ISTR &= ~USB_ISTR_CTR;
}   

   
if (USB->ISTR & USB_ISTR_RESET)
{
   
  USB->ISTR &= ~USB_ISTR_RESET; // сбрасываем флаг прерывания по Reset

            
   USB->BTABLE = BTableOffset; // таблица начинается с 0x0000
      
   *(__IO uint32_t*)(0x40006000) = 0x0040; // начальный адрес USB_ADDR0_TX (такой адрес позволяет в дальнейшем добавить все 8 возможных контрольных точек, каждая имеет размер 1 байт)
   *(__IO uint32_t*)(0x40006004) = 0x0020; // размер исходящих данных - 32 байта USB_COUNT0TX
   *(__IO uint32_t*)(0x40006008) = 0x0060; // начальный адрес USB_ADDR0_RX
   *(__IO uint32_t*)(0x4000600C) = 0x8000; // 32 байта входящих данных USB_ USB_COUNT0RX_BL_SIZE


   USB->EP0R   |= USB_EP_CONTROL; // режим - CONTROL
  USB->EP0R   |= USB_EP_TX_NAK; // Готовы к передаче, но данных для передачи нет
   USB->EP0R   |= USB_EP_RX_VALID; // К приему готов

     //test1 = *(__IO uint32_t*)(0x40006000);

  USB->DADDR |= USB_DADDR_EF;

}


И еще вопрос, есть ли такие программы, которые позволяют мониторить данные с USB в таком состоянии (когда еще не произошла передача дескрипторов)? Может отладка в кейле сбивает работу USB?

Re: STM32 и USB (практика)

Сб июн 04, 2016 17:30:33

isx писал(а):И еще вопрос, есть ли такие программы, которые позволяют мониторить данные с USB в таком состоянии (когда еще не произошла передача дескрипторов)? Может отладка в кейле сбивает работу USB?
Если я правильно понимаю, то для этого еще ставится промежуточная штуковина между хостом и девайсом, которая слушает шину.
В отладкеу у меня ничего не сбивалось, правда у меня Кокос. Я на точках останова выдергивал шнур из USB, чтобы не успел пройти резет.
isx писал(а):USB->ISTR &= ~USB_ISTR_CTR;
Bit 15CTR: Correct transfer
This bit is set by the hardware to indicate that an endpoint has successfully completed a
transaction; using DIR and EP_ID bits softwarecan determine which endpoint requested the
interrupt. This bit is read-only.
USB->EP0R |= USB_EP_TX_NAK; // Готовы к передаче, но данных для передачи нет
USB->EP0R |= USB_EP_RX_VALID; // К приему готов
Подумайте хорошенько что Вы тут сделали, выполните по шагам эти команды.

Re: STM32 и USB (практика)

Сб июн 04, 2016 18:44:54

Z_h_e писал(а): This bit is read-only.

Это я знаю, просто нужно было добавить какую-нибудь строку, чтоб была возможность установить точку останова. Однако прерывание там ни разу не произошло :( .
Z_h_e писал(а):USB->EP0R |= USB_EP_TX_NAK; // Готовы к передаче, но данных для передачи нет
USB->EP0R |= USB_EP_RX_VALID; // К приему готов

Убрал USB->EP0R |= USB_EP_TX_NAK;. Ситуация не изменилась ( .

Re: STM32 и USB (практика)

Сб июн 04, 2016 18:57:48

Насколько я понял - при резете сбрасываются регистры USB и контрольных точек. Поэтому их и настраивают заново при резете. Отладчик обычно не очень шустро работает. И Хост успевает послать резет, запросить дескриптор, подождать ответа, опять послать резет, опять дескриптор и т.д. Как результат установлнные значения успевают сброситься. И наверное при отладке это и происходит.

Re: STM32 и USB (практика)

Сб июн 04, 2016 19:07:32

Ну может состояние Tx NACK нужно. Хотя вроде как по логике он же для передачи :dont_know: . Что там у Вас в EP0R ?
Radist_M писал(а):И наверное при отладке это и происходит.
Между резетами очень приличный интервал времени. Ставите точку останова где-то и в момент останова легко успеваешь выдернуть разъем.

Re: STM32 и USB (практика)

Сб июн 04, 2016 19:21:41

Изображение
Z_h_e писал(а):Между резетами очень приличный интервал времени. Ставите точку останова где-то и в момент останова легко успеваешь выдернуть разъем.

У меня только один резет - в начале. Дальше прерывание вообще молчит...

Re: STM32 и USB (практика)

Сб июн 04, 2016 19:26:47

Странно, я по крайней мере получал прерывание по резету, в нем настраивался и выходил из прерывания. Далее получал прерывание по приему, точнее запрос типа SETUP и смотрю второй принятый байт - там 0x06

Re: STM32 и USB (практика)

Сб июн 04, 2016 19:30:31

Если мне не изменяет память, то хост до трех раз пытается определить что к нему подключено, соответственно резетов должно быть три в Вашем случае и потом винда должна сказать что не удалось понять что к ней подключилось. Поставте счетчик чтоли для резетов. Если этих резетов нет на самом деле, то тут что то не так. Возможно у Вас ложный резет в момент подключения разъема. У меня так бывало. Винда то ругается на неопознанное устройство?

Re: STM32 и USB (практика)

Сб июн 04, 2016 19:46:47

Блин... Простите мне мою рукожопость :) .
Забыл, что отключил пару дней назад пользовательский разъем от компа (портов не хватало).

Резет по прежнему один, однако теперь в памяти вырисовывается запрос дескриптора устройства (если не ошибаюсь). Как тогда мне отследить момент, чтобы вовремя отреагировать на запрос?
Изображение

Re: STM32 и USB (практика)

Сб июн 04, 2016 19:53:58

Во первых правильно настройте EP0R. Для TX Nack должен быть, тогда хост вежливо подождет какое-то время. И вообще вопрос непонятен. По прерыванию, как еще то?

Re: STM32 и USB (практика)

Сб июн 04, 2016 20:03:38

Z_h_e писал(а): Для TX Nack должен быть, тогда хост вежливо подождет какое-то время.

USB->EP0R |= USB_EP_TX_NAK; // Готовы к передаче, но данных для передачи нет
USB->EP0R |= USB_EP_RX_VALID; // К приему готов

А на какую ошибку тогда вы здесь указали? :dont_know:
Z_h_e писал(а): По прерыванию, как еще то?

В том то и дело, что нет никакого прерывания... :dont_know:

Re: STM32 и USB (практика)

Сб июн 04, 2016 20:11:19

isx писал(а):А на какую ошибку тогда вы здесь указали?
Мы с Вами уже обсуждали биты типа togle регистров EPnR. Ссылку давать не буду, не смешно уже. Я же написал Вам, выполните эти операции по шагам.

Re: STM32 и USB (практика)

Сб июн 04, 2016 20:16:34

Так если по умолчанию значения нули, то при попытке записи значений произойдет тот же тугл... :dont_know:
Ответить