Chameleon 0 21 февраля, 2017 Опубликовано 21 февраля, 2017 (изменено) · Жалоба Проц 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. Как вообще эти примеры оказываются работоспособными??? Изменено 21 февраля, 2017 пользователем Chameleon Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 19 21 февраля, 2017 Опубликовано 21 февраля, 2017 · Жалоба UARTPrint("\r\n---USB_IRQHandler") Нельзя внутри обработчиков прерываний выполнять такие толстые и медленные функции. В данном случае эта функция будет выполняться как минимум 2мс, чем затормозит на это время все остальные прерывания, этого достаточно, чтобы USB отвалился. Из прерывания можно тока по-быстрому просемафорить о чем-то флагами или сервисом rtos, и уже в основном коде (задаче) это выполнять. Конечно, можно поиграться приоритетами прерываний и разрешить вытесняющие прерывания, но это в данном случае тупик. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Chameleon 0 21 февраля, 2017 Опубликовано 21 февраля, 2017 · Жалоба Нельзя внутри обработчиков прерываний выполнять такие толстые и медленные функции. В данном случае эта функция будет выполняться как минимум 2мс, чем затормозит на это время все остальные прерывания, этого достаточно, чтобы USB отвалился. Из прерывания можно тока по-быстрому просемафорить о чем-то флагами или сервисом rtos, и уже в основном коде (задаче) это выполнять. Конечно, можно поиграться приоритетами прерываний и разрешить вытесняющие прерывания, но это в данном случае тупик. А вы ожидали чего-то иного c USB? ;) Всю жизнь отлаживал так инициализацию USB. Даже на скорости 9600. Вроде в стандарт уже заложен допуск таких задержек для отладки. Прерывание "Подключение" должно сыпаться непрерывно? Или все таки произойти один раз? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 19 21 февраля, 2017 Опубликовано 21 февраля, 2017 · Жалоба Прерывание "Подключение" должно сыпаться непрерывно? Или все таки произойти один раз? Если нарушить логику подключения тормозами в других прерываниях, то иного ожидать не приходится )) А как выглядит внутри этот самый UARTPrint? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Chameleon 0 21 февраля, 2017 Опубликовано 21 февраля, 2017 · Жалоба Если нарушить логику подключения тормозами в других прерываниях, то иного ожидать не приходится )) А как выглядит внутри этот самый UARTPrint? Прерывания включены только для USB. void UARTPrint(char *s) { for(;;) { while((USART1->SR & USART_SR_TXE) == 0); USART1->DR = *s++; if (*s == 0) break; } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 19 21 февраля, 2017 Опубликовано 21 февраля, 2017 · Жалоба Прерывания включены только для USB. Это не меняет дела: while((USART1->SR & USART_SR_TXE) == 0); USART1->DR = *s++; if (*s == 0) break; Все ясно, на скорости 9600 эта функция будет выполняться еще дольше ... (в 12 раз дольше, чем на 115200) Тупо висим в прерывании, пока не отправится вся строка - как у вас с такой "отладкой" вообще что-то работает?! Если проект без вашей "отладки" нормально работает, то переделывайте отладку на нормальную или откажитесь вовсе от такого метода отладки. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 21 февраля, 2017 Опубликовано 21 февраля, 2017 · Жалоба Все ясно, на скорости 9600 эта функция будет выполняться еще дольше ... (в 12 раз дольше, чем на 115200) Тупо висим в прерывании, пока не отправится вся строка - как у вас с такой "отладкой" вообще что-то работает?! Должно работать. Причина не в "тормозах" отладочной печати. Надо разбираться, почему прерывание от USB постоянно активно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Chameleon 0 21 февраля, 2017 Опубликовано 21 февраля, 2017 · Жалоба Это не меняет дела: Все ясно, на скорости 9600 эта функция будет выполняться еще дольше ... (в 12 раз дольше, чем на 115200) Тупо висим в прерывании, пока не отправится вся строка - как у вас с такой "отладкой" вообще что-то работает?! Если проект без вашей "отладки" нормально работает, то переделывайте отладку на нормальную или откажитесь вовсе от такого метода отладки. Отладка на 115200. 9600 я для примера написал. Время на обработку пакета по стандарту допускается до 50мс без передачи данных и до 500 мс с передачей данных. 50 мс это 500 символов на скорости 115200. Страница текста. Я всегда использовал такую отладку для юсб. Для Silabs, SAM7, NXP. Не было никаких проблем. Один STM32 долбанутый какой-то. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 19 21 февраля, 2017 Опубликовано 21 февраля, 2017 · Жалоба Я всегда использовал такую отладку для юсб. Для Silabs, SAM7, NXP. Не было никаких проблем. Один STM32 долбанутый какой-то. А без вашей "отладки" этот же пример работает нормально? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 199 21 февраля, 2017 Опубликовано 21 февраля, 2017 · Жалоба Нельзя внутри обработчиков прерываний выполнять такие толстые и медленные функции. В данном случае эта функция будет выполняться как минимум 2мс, А как Вы определили что находится у ТС внутри этого самого UARTPrint()? Да ещё и удалённо определили время её выполнения даже не зная что внутри! Поделитесь секретами мастерства!!! Думаю всем тут будет любопытно И вообще - странно как это она может выполняться целых 2мс на Cortex с тактовой в десятки МГц если внутри неё например просто копируется указанная строка в буфер символов??? Или даже просто не строка, а сам указатель. PS: Я подобные отладочные функции вставлял в ISR работающие на частотах в десятки кГц - и всё прекрасно работало. Да - конечно правда без куба ;) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Chameleon 0 21 февраля, 2017 Опубликовано 21 февраля, 2017 · Жалоба А без вашей "отладки" этот же пример работает нормально? Без отладки - да, нормально. Добавляю в начало обработчика прерывания код, просто задержка от балды. { volatile uint32_t x; for (x = 0; x < 2000000; x++); } Устройство определяется через 5 секунд после подключения, но ОПРЕДЕЛЯЕТСЯ. Заменяю эту задержку на UARTPrint("\r\n-IRQ"); Все, ничего не работает. Такое впечатление, что UART и USB какие-то ресурсы поделить не могут. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 199 21 февраля, 2017 Опубликовано 21 февраля, 2017 · Жалоба UARTPrint("\r\n-IRQ"); Вы телепатов ищете? Приведите код этой самой UARTPrint(). А то тут только один телепат пока нашёлся.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Chameleon 0 21 февраля, 2017 Опубликовано 21 февраля, 2017 · Жалоба Вы телепатов ищете? Приведите код этой самой UARTPrint(). А то тут только один телепат пока нашёлся.... См. Post #5 выше. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 19 21 февраля, 2017 Опубликовано 21 февраля, 2017 · Жалоба А как Вы определили что находится у ТС внутри этого самого UARTPrint()? Да ещё и удалённо определили время её выполнения даже не зная что внутри! Поделитесь секретами мастерства!!! Богатый жизненный опыт и умение пользоваться калькулятором ;) Такое впечатление, что UART и USB какие-то ресурсы поделить не могут. Если подряд поставить два-три вызова этой функции, они все вызываются? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Chameleon 0 21 февраля, 2017 Опубликовано 21 февраля, 2017 · Жалоба Богатый жизненный опыт и умение пользоваться калькулятором ;) Если подряд поставить два-три вызова этой функции, они все вызываются? Вроде как нет... Такое впечатление, что обработчик вызывает сам себя. У кортекса есть вложенные прерывания? Надо их запрещать? Может вызваться новое прерывание, пока не завершилость предыдущее? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться