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

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

Чт сен 29, 2016 16:05:12

Radist_M писал(а):Причем прога говорит ,что длина репорта 13 байт, а Report count 12 байт.
Когда отправляется репорт, первым байтом идет идентификатор репорта.

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

Чт сен 29, 2016 17:19:54

Z_h_e писал(а):Когда отправляется репорт, первым байтом идет идентификатор репорта.

Но у меня только один репорт, и вроде как в этом случае report Id не указывается в дескриптору репорта.
Пробовал изменить количество отсылается байт и изменить первый байт на 0. Все так же. Анализатором не удалось глянуть, т.к. шина usb почему то хранила молчание.
Короче так или иначе нужен hid клиент

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

Пн окт 17, 2016 18:02:28

Ребят, помогите прояснить один момент:
1. После успешной энумерации хост постоянно шлет PID IN в 1-ю КТ. Устройство отвечает 0xAA, 0xBB. Причем хост производит опрос с периодом меньше, чем указано в поле bInterval.
Чей то?
Сделал прошивку таким образом, чтобы по приему данных контроллер менял пакет на 0xCC, 0xDD. На стороне компа в программе видно, что отправка успешна и теперь по readfile должен принять новый пакет, а принимаю старый. А если прочитать два раза подряд, то второй раз получаю то что надо. такое ощущение, что некий буфер заполняется и не обнуления пока не будет команды на чтение. Почему так?

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

Пт окт 28, 2016 21:29:40

Ладно, сам разобрался. Могу спокойно принимать/отправлять пару байт без всяких CDC USB-UART и пр.

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

Вс мар 12, 2017 14:13:21

Здравствуйте, тоже начал разбираться с USB. И возникли некоторые трудности. Как мне кажется, не могу правильно настроить нулевую контрольную точку. При возникновении прерывания USB_LP_CAN1_RX0_IRQHandler. В обработчик события SE0, заходит, где и происходит настройка конечной точки.

Дефайны
Код:
#define EP_RX_NAK       0x2000      /* NAKed */
#define EP_RX_VALID     0x3000      /* Valid */
#define EP_CONTROL      0x0200      /* CONTROL EndPoint */


Настраиваю конечную точку, следующим образом:
Код:
// СОбытие сброса
   if (USB->ISTR & USB_ISTR_RESET)
   {    
      // Здесь необходимо настроить контрольгую точку, которая всегда равна 0
      
      // Сбрасываем флаги прерываний
      USB->ISTR = 0;
      // Разрешаем генерировать прерывание по событию удачной передачи и по SE0
      USB->CNTR |= USB_CNTR_CTRM | USB_CNTR_RESETM;
      
      // таблица начинается с 0x0000 USB (или 0x40006000 Flash)
      USB->BTABLE = 0x0000;
   
        // Настраиваем конечную точку
      *(__IO uint32_t*)(0x40006000) = (uint16_t) 0x40;       // начальный адрес USB_ADDR0_TX (такой адрес позволяет в дальнейшем добавить все 8 возможных контрольных точек, каждая имеет размер 1 байт)
      *(__IO uint32_t*)(0x40006004) = (uint16_t) 0x00;       // размер исходящих данных - 32 байта USB_COUNT0TX
      *(__IO uint32_t*)(0x40006008) = (uint16_t) 0x100;      // начальный адрес USB_ADDR0_RX
      *(__IO uint32_t*)(0x4000600C) = (uint16_t) 0x8400;     // 32 байта входящих данных USB_ USB_COUNT0RX_BL_SIZE

       
      USB->EP0R   =    EP_CONTROL |       // Тип - control
                  EP_RX_VALID;       // Включена на прием
      
      USB->DADDR |= USB_DADDR_EF;         // Включаем функцию USB

        // Сбрасываем флаг прерывания
      USB->ISTR &= ~USB_ISTR_RESET;         
   }


А вот в событие удачной транзакции(USB->ISTR & USB_ISTR_CTR) упорно заходить не хочет.

Логический анализатор показывает, что конечная точа не отвечает.(См. во вложениях)

Скажите, где косяц ?

Настройка модуля USB
Код:
void USB_Init(void)
{
NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);
   
   RCC->APB1RSTR |= RCC_APB1RSTR_USBRST;   
   RCC->APB2ENR |=  (RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPAEN);   
   RCC->APB1ENR |= (RCC_APB1ENR_USBEN);   
   RCC->APB1RSTR &= ~RCC_APB1RSTR_USBRST;
   
   /* Turn on analog part */   
   USB->CNTR &= ~USB_CNTR_PDWN;
   
   for (k = 0; k < 240; k++) {} /* Wait at least 1us */   
   /* Release reset */   
   USB->CNTR &= ~USB_CNTR_FRES;
      
   USB->ISTR = ~(USB_ISTR_PMAOVR |USB_ISTR_ERR | USB_ISTR_WKUP | USB_ISTR_SUSP | USB_ISTR_RESET);
   
        USB->CNTR |= (USB_CNTR_CTRM |
              /*USB_CNTR_PMAOVRM |*/
                /*USB_CNTR_ERRM | */
              /*USB_CNTR_WKUPM| */
              /*USB_CNTR_SUSPM | */
              USB_CNTR_RESETM); 
      
   USB->CNTR |= USB_CNTR_RESETM;
   NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);                       // Разрешаем прерывания в NVIC
    //NVIC_EnableIRQ(USBWakeUp_IRQn); //   Разрешаем прерывание USBWakeUp
   NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 1);                  // Устанавливаем приоритет   

}
Вложения
3_Zaprosa_Hosta.JPG
Приходит 3 таких запроса, но конечная точка молчит. После чего происходит еще 2 события SE0, с такими же 3 попытками запроса. И в конце мне выдается, что устройство не опознано.
(46.03 KiB) Скачиваний: 539
Zapros_Hosta.JPG
Запрос от хоста
(49.99 KiB) Скачиваний: 521

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

Вс мар 12, 2017 14:41:20

Сколько раз у Вас происходит событие SE0 , прежде чем хост скажет что не опознал устройство? Если один раз то это от FRES. Если я еще не забыл, то хост три раза пытается достучаться до устройства.

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

Вс мар 12, 2017 21:13:17

Z_h_e писал(а):Сколько раз у Вас происходит событие SE0 , прежде чем хост скажет что не опознал устройство? Если один раз то это от FRES. Если я еще не забыл, то хост три раза пытается достучаться до устройства.

3 раза SE0, затем вылетает сообщение "Неопознаное устройство"
Вложения
Снимок.JPG
3 раза.
(32.74 KiB) Скачиваний: 546

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

Вс мар 12, 2017 22:24:27

Я имел ввиду не сколько раз посылает хост, а сколько раз возникает событие SE0 в МК. Можно счетчик поставить в МК для отладки.

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

Пн мар 13, 2017 12:58:21

Novosib_3000, у меня вроде такая же инициализация при сбросе.
Код:
USB->ISTR = 0;      //clear reset.
//if reset event is occur EP registers a reset and we need to config it's
USB->EP0R = USB_EP0R_EP_TYPE_0|USB_EP0R_STAT_RX|USB_EP0R_STAT_TX_1;//EP address 0, type - control, EP enable (stat_rx - valid), STAT_TX -NAK
USB->EP1R = USB_EP1R_STAT_RX|USB_EP1R_STAT_TX_1|USB_EP1R_EP_TYPE|0x01;//stat_tx-NAK, stat_rx-Valid interrupt ep, 0x01-address         
USB->DADDR = USB_DADDR_EF;//EF enable receive address

Но вот событие удачной транзакции у меня проверяется вот так:
Код:
if (((USB->EP0R)&USB_EP0R_CTR_TX)!=0){
...
}

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

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

Пн мар 13, 2017 17:38:33

Z_h_e писал(а):Я имел ввиду не сколько раз посылает хост, а сколько раз возникает событие SE0 в МК. Можно счетчик поставить в МК для отладки.

1 раз по FRES, и 4 раза пытался достучаться хост. Всего счетчик показал цифру 5.

Добавлено after 7 minutes 53 seconds:
Radist_M писал(а):Novosib_3000, у меня вроде такая же инициализация при сбросе.
Код:
USB->ISTR = 0;      //clear reset.
//if reset event is occur EP registers a reset and we need to config it's
USB->EP0R = USB_EP0R_EP_TYPE_0|USB_EP0R_STAT_RX|USB_EP0R_STAT_TX_1;//EP address 0, type - control, EP enable (stat_rx - valid), STAT_TX -NAK
USB->EP1R = USB_EP1R_STAT_RX|USB_EP1R_STAT_TX_1|USB_EP1R_EP_TYPE|0x01;//stat_tx-NAK, stat_rx-Valid interrupt ep, 0x01-address         
USB->DADDR = USB_DADDR_EF;//EF enable receive address

Но вот событие удачной транзакции у меня проверяется вот так:
Код:
if (((USB->EP0R)&USB_EP0R_CTR_TX)!=0){
...
}

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

Попробовал Ваш код, но контрольная точка не отзывается.

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

Пн мар 13, 2017 19:29:31

Возможно имеет смысл поглядеть другие флаги событий. Может с сопротивлениями в линиях USB что-то не так?

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

Пн мар 13, 2017 19:30:10

Novosib_3000 а чем смотрите что на шине происходит? Анализатором? Давайте посчитаем сколько раз вообще контроллер входит в прерывание. И сколько из них по резету?
И тактирование верно настроено? Могут просто-напросто не совпадать рабочие частоты.

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

Пн мар 13, 2017 21:59:15

Z_h_e писал(а):Возможно имеет смысл поглядеть другие флаги событий. Может с сопротивлениями в линиях USB что-то не так?


Мне кажется, что с сопротивлениями, всё в порядке, т.к. сгенерированный Кубом проект работает. Да и на другой плате, тоже такой же косяк, значит ошибка в программе.

Добавлено after 29 minutes 1 second:
Radist_M писал(а):Novosib_3000 а чем смотрите что на шине происходит? Анализатором? Давайте посчитаем сколько раз вообще контроллер входит в прерывание. И сколько из них по резету?
И тактирование верно настроено? Могут просто-напросто не совпадать рабочие частоты.


Смотрю анализатором, в прерывание по резету заходит 4 раза(см. вложения)

Функция тактирования:

Код:
unsigned char HSE_72Mhz_Init(void)
{
    int TimeOut = 10000;
   
    // Запускаем внешний тактовый генератор
    RCC->CR |= RCC_CR_HSEON;                                    // Включаем HSE OSC
    while(((RCC->CR & RCC_CR_HSERDY) == 0) && (TimeOut > 0))         // Ожидаем готовности HSE
    {
        TimeOut--;
    }
    if(TimeOut == 0) return 1;                                  // HSE не запустился
       
    // Не забываем включать блок защиты CSS
    // Включаем блок CSS, тем самым активируем защиту от сбоя
    RCC->CR |= RCC_CR_CSSON;                                    // Устанавливаем бит CSSON
   
    // Так же не забываем включать предвыборку Flash
    FLASH->ACR |= FLASH_ACR_PRFTBE;                             // Включаем буфер
    FLASH->ACR &= ~(FLASH_ACR_LATENCY);                         // Предочистка регистра
    FLASH->ACR |= FLASH_ACR_LATENCY_2;                         // Пропускать 2 такта
       
    // Не используем делитель для HSE
    RCC->CFGR &= (RCC_CFGR_PLLXTPRE_HSE_Div2);                  // Сбрасываем бит PLLXTPRE
   
    // Источником тактового сигнала для PLL выбираем HSE
    RCC->CFGR |= RCC_CFGR_PLLSRC;                               // Включаем бит PLLSRC
   
    // Настройка делителей производится при выключенном PLL
    // Настраиваем PLL
    RCC->CR &= ~(RCC_CR_PLLON);                                 // Выключаем PLL
    RCC->CFGR &= ~(RCC_CFGR_PLLMULL);                           // Предочистка разрядов
    RCC->CFGR |= RCC_CFGR_PLLMULL9;                             // Умножитель на 9
    RCC->CR |= RCC_CR_PLLON;                                    // Включить генератор
    while(((RCC->CR) & RCC_CR_PLLRDY) == 0){}                   // Ожидаем готовности PLL   
       
    // Выбираем PLL, как источник тактового сигнала
    RCC->CFGR &= ~(RCC_CFGR_SW);                                // Предочистка битов       
    RCC->CFGR |= RCC_CFGR_SW_PLL;                               // Выбираем PLL, как источник тактовой частоты 
    while((RCC->CFGR&RCC_CFGR_SWS)!=0x08){}                     //Ожидаем готовности
       
    // Устанавливаем предделитель на шине APB1
    RCC->CFGR &= ~(RCC_CFGR_PPRE1);                             // Отчишаем биты
    RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;                           // Предделитель на 2   

    // Устанавливаем предделитель для ADC
    RCC->CFGR &= ~(RCC_CFGR_ADCPRE);                            // Отчищаем биты
    RCC->CFGR |= RCC_CFGR_ADCPRE_DIV6;                          // Устанавливаем предделитель на 6
     
    return 0;                                                   // Всё ок, работаем от HSE
}

Код:
void USB_Clock(void)
{
    // Устанавливаем делитель для USB
    RCC->CFGR &= ~(RCC_CFGR_USBPRE);                            // Предочистка регистра
    RCC->CFGR |= RCC_CFGR_USBPRE;                               // Устанавливаем делитель на 1,5
   
   RCC->APB2ENR |= (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_AFIOEN);
   
    // Подаем тактирование на модуль USB
    RCC->APB1ENR |= RCC_APB1ENR_USBEN;                                        // Устанавливаем бит USBEN   

   EXTI->RTSR |= EXTI_RTSR_TR18; // внешнее прерывание №18 (USBWakeUp) по возрастающему фронту
    EXTI->EMR |= EXTI_EMR_MR18; // Включаем событие прерывания USBWakeUp
}
Вложения
Снимок1.JPG
При входе в резет, поднимал и опускал пин.
(28.58 KiB) Скачиваний: 536

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

Вт мар 14, 2017 07:58:41

Novosib_3000 писал(а):RCC->CFGR |= RCC_CFGR_USBPRE; // Устанавливаем делитель на 1,5
Вы вроде как не обозначили контроллер, но в RM008 включение этого бита отключает деление совсем.

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

Вт мар 14, 2017 09:08:48

Z_h_e писал(а): Вы вроде как не обозначили контроллер, но в RM008 включение этого бита отключает деление совсем.

Странно в моем F103 это именно деление в 1,5 раза. МБ это зависит от контроллера?
Если прикинуть частоту тактирования USB Novosib_3000 и если ядро заводится на 72 мГц, то 72/2/1,5=24 МГц. А надо сколько? По даташиту на мой контроллер частота тактирования USB 48МГц.

Я так понял, кварц на 8 МГц.
Код:
RCC->CFGR |= RCC_CFGR_PLLMULL9;                             // Умножитель на 9
RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;                           // Предделитель на 2
RCC->CFGR |= RCC_CFGR_USBPRE;                               // Устанавливаем делитель на 1,5

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

Вт мар 14, 2017 15:28:47

Конечно следует обозначить что за МК.

Изображение

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

Вт мар 14, 2017 19:42:32

Тупанул, ошибся, фигню написал. Признаю. В 103 так-же. Если бит USBPRE установлен, то частота не делится. Если сброшен, то делитель включен.

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

Вт мар 14, 2017 21:08:44

Микроконтроллер 103, кварц на 8 Мгц, вы оказались правы, ошибка закрались в системе тактирования. Как раз именно, в предделителе USB. Нужно было сбрость бит USBPRE, а не устанавливать. Переписал функцию системы тактирования, и теперь в прерывание заходит. Буду дальше пробираться сквозь тернии. Огромное спасибо, что помогли, очень Вам за это благодарен.

Исправленная система тактирования:
Код:
int TimeOut = 10000;
   
    // Запускаем внешний тактовый генератор
    RCC->CR |= RCC_CR_HSEON;                                    // Включаем HSE OSC
    while(((RCC->CR & RCC_CR_HSERDY) == 0) && (TimeOut > 0))         // Ожидаем готовности HSE
    {
        TimeOut--;
    }
    if(TimeOut == 0) return 1;                                  // HSE не запустился
   
    // Не забываем включать блок защиты CSS
    // Включаем блок CSS, тем самым активируем защиту от сбоя
    RCC->CR |= RCC_CR_CSSON;                                    // Устанавливаем бит CSSON
   
    // Так же не забываем включать предвыборку Flash, т.к. Flash
    // не может работать на большой скорости. В reference manual написано, что
    // буфер предвыборки Flash необходимо включать, когда системная частота меньше,
    // чем 24 МГц и не используется ни один делитель.
    FLASH->ACR |= FLASH_ACR_PRFTBE;                             // Включаем буфер
    FLASH->ACR &= ~(FLASH_ACR_LATENCY);                         // Предочистка регистра
    FLASH->ACR |= FLASH_ACR_LATENCY_2;                          // Пропускать 2 такта
   
    // Не использовать делитель для HSE
    RCC->CFGR &= ~RCC_CFGR_PLLXTPRE;            // Сбрасываем бит PLLXTPRE                         
   
    // Источником тактового сигнала для PLL выбираем HSE
    RCC->CFGR |= RCC_CFGR_PLLSRC;                               // Включаем бит PLLSRC
   
    // Настройка делителей производится при выключенном PLL
    // Настраиваем PLL
    RCC->CR &= ~(RCC_CR_PLLON);                                 // Выключаем PLL
    RCC->CFGR &= ~(RCC_CFGR_PLLMULL);                           // Предочистка разрядов
    RCC->CFGR |= RCC_CFGR_PLLMULL9;                             // Умножитель на 9
    RCC->CR |= RCC_CR_PLLON;                                    // Включить генератор
    while(((RCC->CR) & RCC_CR_PLLRDY) == 0){}                   // Ожидаем готовности PLL   
       
    // Выбираем PLL, как источник тактового сигнала
    RCC->CFGR &= ~(RCC_CFGR_SW);                                // Предочистка битов       
    RCC->CFGR |= RCC_CFGR_SW_PLL;                               // Выбираем PLL, как источник тактовой частоты
    while((RCC->CFGR&RCC_CFGR_SWS)!= RCC_CFGR_SWS_PLL){}        //Ожидаем готовности
       
    // Устанавливаем предделитель на шине APB1
    RCC->CFGR &= ~(RCC_CFGR_PPRE1);                             // Отчишаем биты
    RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;                           // Предделитель на 2   

    // Устанавливаем предделитель для ADC
    RCC->CFGR &= ~(RCC_CFGR_ADCPRE);                            // Отчищаем биты
    RCC->CFGR |= RCC_CFGR_ADCPRE_DIV6;                          // Устанавливаем предделитель на 6
       
    // Устанавливаем делитель для USB
    RCC->CFGR &= ~(RCC_CFGR_USBPRE);                          // Устанавливаем делитель на 1,5   
                                     
    return 0;

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

Сб апр 15, 2017 17:23:29

Всем, привет, появилось время, и снова возвращаюсь к изучению USB. Появился маленький вопрос. После сброса.

Вначале, всё хорошо.

Хост отправляет пакет SETUP контрольной точке 0, затем отправляет запрос на получение дескриптора, затем контрольная точка отвечаем ACK, говоря тем самым, что она получила пакеты.

А вот дальше всё ломается, хост, отправляем пакет IN, за ним следует непонятный пакет(смотри во вложениях ), то ли это ответ контрольной точки 0, то ли хост шлет какие-то данные?

Дальше вроде бы всё налаживается.

Хост отправляет пакет IN, за ним идет очень длинный пакет: поля, которого у меня обозначены как Error, я так понимаю, это как раз дескриптор устройства, который, отправляет конечная точка, и после этого пакета приходит пакет квитирования ACK, это видимо хост отвечает, что принял данные.

Вопрос? Что это за непонятный пакет(смотри во вложениях), может быть это контрольная точка так отвечает, говоря хосту, что сейчас она занята и не может ответить. Или это еще что-то? Прошу помощи.
Вложения
Непонятный пакет.JPG
(62.54 KiB) Скачиваний: 596

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

Сб апр 15, 2017 18:07:37

По внешнему виду, ИМХО, какой-то кривой пакет :dont_know: Когда точка занята, она отвечает NACKом.

----------
Еще хочу на счет анализатора протокола добавить. Я вчера потерял пол дня времени, пытаясь разобраться с I2C. Первая часть пакета отображалась все нормально. Вторая часть (через 100 мс) сплошные старты и стопы вместо данных. В итоге оказалось второй пакет данных был нормальным, почему то анализатор протокола только половину правильно декодировал. Справедливости ради хочу добавить, что сама диаграмма то была правильной во обоих пакетах (я потом разглядел), а у Вас какой-то узкий импульс, вроде таких не должно быть. Я не хочу сказать что у Вас анализатор врет, но оказалось полностью доверять ему особо тоже не стоит.
Ответить