реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> suspend & resume USB LPC23xx, зависание USB контроллера
andrvisht
сообщение Jan 17 2011, 18:48
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064



Не могу разобраться с проблемой определения девайса после suspend.
событие resume отлавливается, но сам контроллер не сообщает драйверу о готовности возобновить передачу.
В качестве драйвера использую Thesycon.
В качестве контроллера LPC2368
В качестве управляющей программы - пример от tnkernel

Логическим анализатором засканил вариант отработки resume на JLink, и тестируемого устройства.
При resume на D+ появляется лог 0 на 1ms, после чего происходит обмен и снова в подтверждение D+ становиться в лог 0 на 1ms.
В моем случае подтверждения не получается.

Аналогичная реакция происходит и при подключении устройства к USB но в этом случае подтверждение есть.

Проверяю следующим образом, в device manager Windows отключаю драйвер (при этом ловим suspend) а после включаю,
отлавливаю resume но далее контроллер USB не выдает подтверждение, и процесс выдает ошибку.
Если в момент после suspend ресетнуть контроллер, то все проходит нормально, и драйвер активируется без проблем.

Лог событий из demo приложения от Thesycon:
вставляем
Код
OnDeviceChange message: 00000007 (DBT_DEVNODES_CHANGED)
OnDeviceChange message: 00008004 (DBT_DEVICEREMOVECOMPLETE)
The USB device \\?\USB#Vid_16c0&Pid_05dc#000010#{325ddf96-938c-11d3-9e34-0080c82727f4} has been removed.
OnDeviceChange message: 00000007 (DBT_DEVNODES_CHANGED)
OnDeviceChange message: 00008000 (DBT_DEVICEARRIVAL)
A new USB device has been plugged in and is now available.
Device path is: \\?\USB#Vid_16c0&Pid_05dc#000010#{325ddf96-938c-11d3-9e34-0080c82727f4}.
OnDeviceChange message: 00000007 (DBT_DEVNODES_CHANGED)

отключаем драйвер
Код
OnDeviceChange message: 00000007 (DBT_DEVNODES_CHANGED)
OnDeviceChange message: 00008004 (DBT_DEVICEREMOVECOMPLETE)
The USB device \\?\USB#Vid_16c0&Pid_05dc#000010#{325ddf96-938c-11d3-9e34-0080c82727f4} has been removed.

задествуем драйвер после ресета программы
Код
OnDeviceChange message: 00000007 (DBT_DEVNODES_CHANGED)
OnDeviceChange message: 00008000 (DBT_DEVICEARRIVAL)
A new USB device has been plugged in and is now available.
Device path is: \\?\USB#Vid_16c0&Pid_05dc#000010#{325ddf96-938c-11d3-9e34-0080c82727f4}.
OnDeviceChange message: 00000007 (DBT_DEVNODES_CHANGED)

если не делать сброс программы то:
Код
OnDeviceChange message: 00000007 (DBT_DEVNODES_CHANGED)
и через секунду еще раз
OnDeviceChange message: 00000007 (DBT_DEVNODES_CHANGED)

после чего в состоянии устройства USBIO появляется ошибка:
"Запуск этого устройства невозможен. (Код 10)"
проверял как на BUS Powered так и на Self Powered, разницы нет.
Подскажите в каком направлении двигаться, как отловить проблему, чем засканить обмен более детально, какие варианты попробовать ?
Go to the top of the page
 
+Quote Post
kovigor
сообщение Jan 17 2011, 19:58
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 5 273
Регистрация: 30-03-10
Пользователь №: 56 295



Цитата(andrvisht @ Jan 17 2011, 21:48) *
Подскажите в каком направлении двигаться, как отловить проблему, чем засканить обмен более детально, какие варианты попробовать ?


Много раз боролся с этой проблемой на разных МК. Всегда использовал цифровой осиллограф, синхронизировал его по заданному событию и рассматривал момент пробуждения. Вариантов масса. Но чаще всего я так или иначе неправильно формировал временную диаграмму Upstream Resume. В случае Remote Wakeup все было гораздо проще. Но, опять же, помогает осциллограф, а также вдумчивое чтение даташита и часто эрраты (!). Последний раз некорректное пробуждение было вызвано тем, что после ухода МК ARM9 в Suspend разрушались данные в ИС динамической памяти. Отлавливал неделю, но отловил же. Удачи ...
P.S. В качестве подопытного кролика очень удобно использовать USB - мышку или клавиатуру. Ценность их в том, что тут можно как захватить внешний Upstream Resume, так и в любой момент сгенерировать свой собственный Remote Wakeup ...

Сообщение отредактировал kovigor - Jan 17 2011, 20:01
Go to the top of the page
 
+Quote Post
andrvisht
сообщение Jan 17 2011, 21:52
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064



Цитата(kovigor @ Jan 17 2011, 23:58) *
Много раз боролся с этой проблемой на разных МК. Всегда использовал цифровой осиллограф, синхронизировал его по заданному событию и рассматривал момент пробуждения. Вариантов масса. Но чаще всего я так или иначе неправильно формировал временную диаграмму Upstream Resume.

насколько я себе думал, то пробуждение возложено на встроенный контроллер, и все диаграммы он должен формировать аппаратно, без участия написанного кода. Пользовательское ПО должно обеспечить снижение энергопотребления. Или я ошибаюсь ?
Проблема в том что что-то в модуле USB происходит такое, из за чего он виснет. Но, по этому поводу в даташите никаких намеков. suspend описан только как событие, и никаких рекомендаций или последовательностей действий я не нашел.
Errata тоже молчит по этому поводу.
Go to the top of the page
 
+Quote Post
kovigor
сообщение Jan 17 2011, 22:34
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 5 273
Регистрация: 30-03-10
Пользователь №: 56 295



Цитата(andrvisht @ Jan 18 2011, 00:52) *
насколько я себе думал, то пробуждение возложено на встроенный контроллер, и все диаграммы он должен формировать аппаратно, без участия написанного кода.


Да ну, какой там. Чего стоят одни только прерывания по Resume/Wakeup, которые контроллер способен генерировать. И вообще, программной обработки там предостаточно. Виснет не сам USB движок, виснет ваше ПО. А вот почему - вопрос. Например, потому, что некорректно обрабатывается прерывание(я). Или вы перед усыплением понижаете тактовую частоту, засыпаете с пониженной частотой и с ней же просыпаетесь, и в результате продолжаете работать, считая, что частота не пониженная, а обычная, или вообще выключаете тактирование USB перед засыпанием, или выключаете одну из PLL. Причин тысяча. Какая ваша ? Это вы должны выяснить сами ...

Сообщение отредактировал kovigor - Jan 17 2011, 22:35
Go to the top of the page
 
+Quote Post
andrvisht
сообщение Jan 20 2011, 19:15
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064



Решил пойти другим путем.
1. скачал с сайта производителя тут пример AN10759 USB bootloader (LPC23xx) (v.1.0, 2008-10-14)
Там контроллер выдает себя за Mass Storage и появляется в винде в виде диска с файлом firmware.
2. Залил его в мой контроллер.
И собственно все те же проблемы. Находиться диск, на нем файл, винда не ругается, применяет стандартный драйвер.
Но попытка воспроизвести отключение драйвера с последующей активацией вызывает точно такие же проблемы.

Сами функции обработки suspend и Resume есть, но они пустые. Собственно как и у меня. Никаких действий с вводом контроллера в спящий режим не производиться.
Может в этом и проблема ?
Тогда вопрос, как правильно это делать ? В документации на контроллер никаких упоминаний про рекомендуемые действия после suspend и resume я не нашел. Может не там искал, или не так понял...
Go to the top of the page
 
+Quote Post
kovigor
сообщение Jan 20 2011, 20:06
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 5 273
Регистрация: 30-03-10
Пользователь №: 56 295



Цитата(andrvisht @ Jan 20 2011, 22:15) *
Может не там искал, или не так понял...


Там надо воздействовать как минимум на регистр PCON. Вот обработчик прерывания, извлеченный из одного из моих проектов для LPC214x. Именно он обрабатывает Suspend и переводит МК в соотв. режим. Весь проект выложить, к сожалению, не могу. Если что будет непонятно - спросите ...

http://zalil.ru/30373924

P.S. Игрался с HID - примером от Кейла. Там Suspend работает некорректно. Было это давно, деталей не помню ...

P.P.S.

Люди просят весь проект. Вот он. Пароль сообщу в ответе на личное сообщение ...

http://zalil.ru/30376114

Сообщение отредактировал kovigor - Jan 21 2011, 09:39
Go to the top of the page
 
+Quote Post
andrvisht
сообщение Jan 22 2011, 12:30
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064



Цитата(kovigor @ Jan 21 2011, 00:06) *
Там надо воздействовать как минимум на регистр PCON. Вот обработчик прерывания, извлеченный из одного из моих проектов для LPC214x.

Большое Спасибо, за предоставленный код, основную идею понял, но на LPC23xx все оказалось несколько иначе, возможно я опять все попутал ...
Итак имеем бит USB_NEED_CLK который должен сброситься после 2ms как только активность на шине прекратиться.
Once USB_NEED_CLK becomes one, it it resets to zero 5 ms after the last packet has been
received/sent, or 2 ms after the Suspend Change (SUS_CH) interrupt has occurred.

В другом месте говориться о том что состояние биты DEV_CLK_EN и AHB_CLK_EN должны быть 0 0 и только после этого USB_NEED_CLK будет равен нулю.
After entering the suspend state with DEV_CLK_EN and AHB_CLK_EN cleared, the
DEV_CLK_ON and AHB_CLK_ON will be cleared when the corresponding clock turns off.
When both bits are zero, USB_NEED_CLK will be low, indicating that the chip can be put
into Power Down mode by writing to the PCON register.

На самом деле USB_NEED_CLK всегда 1.
Errata утверждает что данная проблема имела место в ревизии -, а у меня B. Но предложенный ими вариант решения проблемы испробовал.
After setting the PCUSB bit in PCONP (located at 0xE01F C0C4), write 0x1 to address
0xFFE0C008. The USB_NEED_CLK signal will now function correctly. Writing to address
0xFFE0C008 only needs to be done once after each chip reset.

чудо произошло, но не надолго. При таком подходе контроллер абсолютно никак не реагирует на то, чтобы ответить на запрос шины, до дискриптора даже не доходит. Хотя если бродить JTAG-ом то все находиться как нужно, при сбросе контроллера и запуске отладки.
Тогда сделал следущее:
Код
    
FIO2DIR = (1<<3);
if (!(FIO2PIN & (1<<2))) // кнопка для отладки
{
    *((int*)0xFFE0C008) = 1;                           // без этого USB_NEED_CLK всегда 1
    if (FIO2PIN & (1<<3)) FIO2CLR = (1<<3);  else FIO2SET |= (1<<3);  // проверка входа в режим
    USBClkCtrl &= ~0x12;                        // без этого USB_NEED_CLK всегда 1
    while ((USBClkSt & 0x12) != 0x00);
    while (USB_INT_STAT & 0x00000100);
    INTWAKE = 0x20;
    PCON = 0x06;
    USBClkCtrl = 0x12;                        /* Dev clock, AHB clock enable  */
    while ((USBClkSt & 0x12) != 0x12);
    INTWAKE = 0x00;

}

при этом во первых....
Код
if (FIO2PIN & (1<<3)) FIO2CLR = (1<<3);  else FIO2SET |= (1<<3);

срабатывает только при отладке JTAG
Код
PCON = 0x06;
- срабатывает всегда (смотрю по потребляемому току), но проснуться контроллер уже не может.

Допустим мы пропустим все режимы сна, а просто после запуска и определения устройства остановимся на suspend, выключим а затем включим драйвер, и продолжим выполнение программы.
По логике код должен продолжить функционирование как ни в чем не бывало, но проблема остается все в той же форме.
Go to the top of the page
 
+Quote Post
andrvisht
сообщение Jan 27 2011, 08:24
Сообщение #8


Местный
***

Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064



привожу результаты последних исследований.
Цитата
*((int*)0xFFE0C008) = 1;

после этого ядро USB отваливается, J-LINK показавает в области памяти USB 0xAAAAAAAA
т.о. действия описанные в Errata можно расценивать как дезу, ну или все таки оно работает на единственной ревизии "-"
найти которую уже не получиться.
т.о. имеем проблему с тем, что USB_NEED_CLK никогда не становиться равным 0.
похожая проблема поднималась тут и тут и осталась без решения.
Кроме предложенного вырианта от NXP, был проверен пакет code.bundle.lpc23xx.lpc24xx.uvision.zip
в котором вроде как, suspend и resume обрабатываются.
результат не удивил, при suspend происходит зависание на цикле ожидания USB_NEED_CLK;
непонятно как это работало у человека, который писал этот код cranky.gif

Есть ли у кого из присутсвующих возможность проверить данный код на платах ENG_BOARD_LPC24XX
или KEIL_BOARD_LPC23XX или SK-LPC2378 (c мелкими изменениями в инициализации) ?

Есть ли адрес службы поддержки NXP (не то что на сайте, а тот с которого отвечают sm.gif ), или какие другие предложения по поиску решения ?
Go to the top of the page
 
+Quote Post
kovigor
сообщение Jan 27 2011, 09:17
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 5 273
Регистрация: 30-03-10
Пользователь №: 56 295



Цитата(andrvisht @ Jan 27 2011, 11:24) *
или какие другие предложения по поиску решения ?


Я с LPC23xx не работал, посему на роль носителя абсолютной истины не претендую. Но все же. Вчитайтесь в описание бита "AP_CLK" в п.9.3 описания на LPC214x (UM10139):

9.3 Set Mode (Command: 0xF3, Data: write 1 byte)

AP_CLK = 0: usb_needclk is functional; 48 MHz clock can be stopped when
the device enters suspend state.
AP_CLK = 1: usb_needclk always have the value 1. 48 MHz clock cannot be
stopped in case when the device enters suspend state.

Вообще, в чем проблема ? В том, что вы не знаете, что на шине пропали маркеры SOF и вы не знаете, когда переходить в Suspend ?

Go to the top of the page
 
+Quote Post
andrvisht
сообщение Jan 27 2011, 09:47
Сообщение #10


Местный
***

Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064



Цитата(kovigor @ Jan 27 2011, 12:17) *
Вообще, в чем проблема ? В том, что вы не знаете, что на шине пропали маркеры SOF и вы не знаете, когда переходить в Suspend ?


в моем случае AP_CLK = 0, т.е. я должен дождаться пока usb_needclk не сброситься, и потом могу убрать тактирование с USB модуля. SOF пропадает, это я вижу на осциллографе, но вот usb_needclk продолжает быть 1. и соответственно дальше ничего не возможно делать.
Получается, что я не вижу аппаратно пропадание SOF.
Go to the top of the page
 
+Quote Post
kovigor
сообщение Jan 27 2011, 10:05
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 5 273
Регистрация: 30-03-10
Пользователь №: 56 295



Цитата(andrvisht @ Jan 27 2011, 12:47) *
в моем случае AP_CLK = 0, т.е. я должен дождаться пока usb_needclk не сброситься, и потом могу убрать тактирование с USB модуля. SOF пропадает, это я вижу на осциллографе, но вот usb_needclk продолжает быть 1. и соответственно дальше ничего не возможно делать.
Получается, что я не вижу аппаратно пропадание SOF.


Хорошо. А если не обращать на этот бит внимания, а просто, например, раз в миллисекунду в обработчике любого подходящего прерывания проверять USBDevIntSt.DEV_STAT ? Этот бит укажет вам на "USB suspend change". Дальше подаете команду: Get Device Status (Command: 0xFE, Data: read 1 byte). Она выдаст вам, пропали маркеры на шине или не пропали (см. Table230, описание битов SUS и SUS_CH). Дальше все просто, и usb_needclk оказывается не нужным. Я, правда, так не делал, поэтому ничего не обещаю ...
Go to the top of the page
 
+Quote Post
andrvisht
сообщение Jan 27 2011, 10:14
Сообщение #12


Местный
***

Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064



Цитата(kovigor @ Jan 27 2011, 13:05) *
Хорошо. А если не обращать на этот бит внимания, а просто, например, раз в миллисекунду в обработчике любого подходящего прерывания проверять USBDevIntSt.DEV_STAT ? Этот бит укажет вам на "USB suspend change". Дальше подаете команду: Get Device Status (Command: 0xFE, Data: read 1 byte). Она выдаст вам, пропали маркеры на шине или не пропали (см. Table230, описание битов SUS и SUS_CH). Дальше все просто, и usb_needclk оказывается не нужным. Я, правда, так не делал, поэтому ничего не обещаю ...

Само прерывание по suspend() работает, с FE попробую, но ... ведь тот же usb_needclk используется для просыпания контроллера, и соответственно он уже не проснется.
Go to the top of the page
 
+Quote Post
kovigor
сообщение Jan 27 2011, 10:33
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 5 273
Регистрация: 30-03-10
Пользователь №: 56 295



Цитата(andrvisht @ Jan 27 2011, 13:14) *
Само прерывание по suspend() работает, с FE попробую, но ... ведь тот же usb_needclk используется для просыпания контроллера, и соответственно он уже не проснется.


Ну что я могу сказать ? Заведите линию D+ или D- на вход внешнего прерывания МК, можно через КМОП - повторитель вроде SN74LVC1G07. На 12МБит все должно работать. У меня, во всяком случае, работало и работает. Т.е., вы обнаружили, что маркеры SOF пропали. Чудесно. Теперь линия D+ всегда стоит в "1". Настраиваем внешнее прерывание на возникновение по спадающему фронту сигнала на входе прерывания МК и засыпаем, и спим, сколько угодно. Как только по шине пройдет первый маркер, у вас на входе прерывания напряжение упадет до нуля, произойдет прерывание и МК проснется. Думаю, это единственный способ решить вашу проблему ...

Сообщение отредактировал kovigor - Jan 27 2011, 10:34
Go to the top of the page
 
+Quote Post
andrvisht
сообщение Jan 28 2011, 06:39
Сообщение #14


Местный
***

Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064



Цитата(kovigor @ Jan 27 2011, 13:33) *
Ну что я могу сказать ? Заведите линию D+ или D- на вход внешнего прерывания МК, можно через КМОП - повторитель вроде SN74LVC1G07. На 12МБит все должно работать. У меня, во всяком случае, работало и работает.


Была такая мысль, но я пока её отгонял. Написал в support и на форум NXP. Подождем результатов, а пока попробую реализовать по вашей схеме.
Go to the top of the page
 
+Quote Post
kovigor
сообщение Jan 28 2011, 09:11
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 5 273
Регистрация: 30-03-10
Пользователь №: 56 295



Цитата(andrvisht @ Jan 28 2011, 10:39) *
Была такая мысль, но я пока её отгонял. Написал в support и на форум NXP. Подождем результатов, а пока попробую реализовать по вашей схеме.


Моя схема работает на LPC214x. На LPC23xx не пробовал и ничего не обещаю ...
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 04:00
Рейтинг@Mail.ru


Страница сгенерированна за 0.0149 секунд с 7
ELECTRONIX ©2004-2016