Перейти к содержанию
    

STM32 OTG USB проблема с отладкой

Проц STM32F411RE.

 

Сгенерил в кубе и собрал в кейле пример виртуального ком-порта (CDC класс). Все работает.

Когда пытаюсь добавить в код вывод отладки через UART, все разваливается.

 

Просто добавляю в начало обработчика OTG_USB_IRQHandler строку

 

UARTPrint("\r\n---USB_IRQHandler")

 

и после этого в терминале вижу бесконечно только эту стоку и само устройство перестает определяться.

Скорость UART 115200.

 

До этого всегда делал отладку по этому принципу и для silabs и для SAM7, никогда она не мешала.

В STM32 USB имеет какие-то критичные тайм-ауты?

 

---------- Продолжение ---------------------

 

Через отладчик выяснил, что USB контроллер завален прерываниями. Например код обработки

 

/* Handle Connection event Interrupt */
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT))
    {
      HAL_PCD_ConnectCallback(hpcd);
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT);
    }

 

Это прерывание сыплется непрерывно.

 

Дефайн __HAL_PCD_CLEAR_FLAG определен как

 

#define __HAL_PCD_CLEAR_FLAG(__HANDLE__, __INTERRUPT__)    (((__HANDLE__)->Instance->GINTSTS) &= (__INTERRUPT__))

 

Если упростить, получится

 

GINTSTS &= 0x40000000;

 

Но ведь для сброса флага прерывания в него надо записывать "1" ????

Т.е. делать так:

GINTSTS |= 0x40000000;

 

И так "сбрасываются" все биты прерываний в регистре GINTSTS.

 

Как вообще эти примеры оказываются работоспособными???

 

Изменено пользователем Chameleon

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

UARTPrint("\r\n---USB_IRQHandler")

 

Нельзя внутри обработчиков прерываний выполнять такие толстые и медленные функции.

В данном случае эта функция будет выполняться как минимум 2мс, чем затормозит на это время все остальные прерывания, этого достаточно, чтобы USB отвалился.

Из прерывания можно тока по-быстрому просемафорить о чем-то флагами или сервисом rtos, и уже в основном коде (задаче) это выполнять.

Конечно, можно поиграться приоритетами прерываний и разрешить вытесняющие прерывания, но это в данном случае тупик.

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нельзя внутри обработчиков прерываний выполнять такие толстые и медленные функции.

В данном случае эта функция будет выполняться как минимум 2мс, чем затормозит на это время все остальные прерывания, этого достаточно, чтобы USB отвалился.

Из прерывания можно тока по-быстрому просемафорить о чем-то флагами или сервисом rtos, и уже в основном коде (задаче) это выполнять.

Конечно, можно поиграться приоритетами прерываний и разрешить вытесняющие прерывания, но это в данном случае тупик.

 

 

А вы ожидали чего-то иного c USB? ;)

 

Всю жизнь отлаживал так инициализацию USB. Даже на скорости 9600. Вроде в стандарт уже заложен допуск таких задержек для отладки.

 

Прерывание "Подключение" должно сыпаться непрерывно? Или все таки произойти один раз?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Прерывание "Подключение" должно сыпаться непрерывно? Или все таки произойти один раз?

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

 

А как выглядит внутри этот самый UARTPrint?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

А как выглядит внутри этот самый UARTPrint?

 

Прерывания включены только для USB.

 

void UARTPrint(char *s)
{
    for(;;)
    {
        while((USART1->SR & USART_SR_TXE) == 0);
        USART1->DR = *s++;
        if (*s == 0) break;
    }
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Прерывания включены только для USB.

Это не меняет дела:

 

while((USART1->SR & USART_SR_TXE) == 0);
USART1->DR = *s++;
if (*s == 0) break;

Все ясно, на скорости 9600 эта функция будет выполняться еще дольше ... (в 12 раз дольше, чем на 115200)

Тупо висим в прерывании, пока не отправится вся строка - как у вас с такой "отладкой" вообще что-то работает?!

 

Если проект без вашей "отладки" нормально работает, то переделывайте отладку на нормальную или откажитесь вовсе от такого метода отладки.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Все ясно, на скорости 9600 эта функция будет выполняться еще дольше ... (в 12 раз дольше, чем на 115200)

Тупо висим в прерывании, пока не отправится вся строка - как у вас с такой "отладкой" вообще что-то работает?!

Должно работать. Причина не в "тормозах" отладочной печати.

 

Надо разбираться, почему прерывание от USB постоянно активно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это не меняет дела:

 

 

Все ясно, на скорости 9600 эта функция будет выполняться еще дольше ... (в 12 раз дольше, чем на 115200)

Тупо висим в прерывании, пока не отправится вся строка - как у вас с такой "отладкой" вообще что-то работает?!

 

Если проект без вашей "отладки" нормально работает, то переделывайте отладку на нормальную или откажитесь вовсе от такого метода отладки.

 

Отладка на 115200. 9600 я для примера написал. Время на обработку пакета по стандарту допускается до 50мс без передачи данных и до 500 мс с передачей данных. 50 мс это 500 символов на скорости 115200. Страница текста.

 

Я всегда использовал такую отладку для юсб. Для Silabs, SAM7, NXP. Не было никаких проблем. Один STM32 долбанутый какой-то.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я всегда использовал такую отладку для юсб. Для Silabs, SAM7, NXP. Не было никаких проблем. Один STM32 долбанутый какой-то.

А без вашей "отладки" этот же пример работает нормально?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нельзя внутри обработчиков прерываний выполнять такие толстые и медленные функции.

В данном случае эта функция будет выполняться как минимум 2мс,

А как Вы определили что находится у ТС внутри этого самого UARTPrint()?

Да ещё и удалённо определили время её выполнения даже не зная что внутри! Поделитесь секретами мастерства!!! Думаю всем тут будет любопытно :biggrin:

И вообще - странно как это она может выполняться целых 2мс на Cortex с тактовой в десятки МГц если внутри неё например просто копируется указанная строка в буфер символов???

Или даже просто не строка, а сам указатель.

 

PS: Я подобные отладочные функции вставлял в ISR работающие на частотах в десятки кГц - и всё прекрасно работало. Да - конечно правда без куба ;)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А без вашей "отладки" этот же пример работает нормально?

 

Без отладки - да, нормально.

 

Добавляю в начало обработчика прерывания код, просто задержка от балды.

 

{
   volatile uint32_t x;
   for (x = 0; x < 2000000; x++);
}

 

Устройство определяется через 5 секунд после подключения, но ОПРЕДЕЛЯЕТСЯ.

 

Заменяю эту задержку на

 

    UARTPrint("\r\n-IRQ");

Все, ничего не работает.

Такое впечатление, что UART и USB какие-то ресурсы поделить не могут.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

UARTPrint("\r\n-IRQ");

Вы телепатов ищете? Приведите код этой самой UARTPrint().

А то тут только один телепат пока нашёлся....

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы телепатов ищете? Приведите код этой самой UARTPrint().

А то тут только один телепат пока нашёлся....

 

См. Post #5 выше.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А как Вы определили что находится у ТС внутри этого самого UARTPrint()?

Да ещё и удалённо определили время её выполнения даже не зная что внутри! Поделитесь секретами мастерства!!!

Богатый жизненный опыт и умение пользоваться калькулятором ;)

 

 

 

Такое впечатление, что UART и USB какие-то ресурсы поделить не могут.

Если подряд поставить два-три вызова этой функции, они все вызываются?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Богатый жизненный опыт и умение пользоваться калькулятором ;)

 

 

 

 

Если подряд поставить два-три вызова этой функции, они все вызываются?

 

Вроде как нет... Такое впечатление, что обработчик вызывает сам себя.

У кортекса есть вложенные прерывания? Надо их запрещать? Может вызваться новое прерывание, пока не завершилость предыдущее?

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...