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

Ресет USB устройства хостом

Разработано CDC USB устройство с питанием от шины. Пишется PC программа для настройки и апгрейда устройства.

Из PC программы необходимо сделать ресет устройства для перехода в наш бутлодер.

Пробуем DeviceIoControl(), но что-то не выходит. Кто-нибудь делал такую вещь??? Помогите плиз.

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


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

Мы делали в системе команд, передаваемых по CDC (виртуальному COM-порту), команду перейти в Boot.

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


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

To Alex11:

Девайс работает под 1С по CAS протоколу. А наша РС программа нужна лишь для апгрейда прошивки, в ней другой протокол и в бутлодере соответственно тоже. Не хотелось бы парсить лишнюю команду в основной программе процом, но видимо придется ввести уникальную на ресет. Вариант с ресетом девайса от хоста выглядит наиболее удачным.

Смысл в разделении протоколов.

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


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

Из PC программы необходимо сделать ресет устройства для перехода в наш бутлодер.

Пробуем DeviceIoControl(), но что-то не выходит. Кто-нибудь делал такую вещь???

 

В протоколе USB нет и не может быть такой команды, получатель которой делал бы себе харакири :). Поэтому копать надо не в сторону поиска такой экзотической USB-команды, а в сторону интерпретации уже имеющихся в протоколе команд.

Например, интерфейсная команда SEND_BREAK используется крайне редко, вот на ее обработчик (в вашем USB-устройстве) вы могли бы повесить ресет (блокировать прерывания + поставить самый быстрый WatchDog + войти в вечный цикл). Тогда для ресета микропроцессора было бы достаточно послать на виртуальный COM-порт команду с помощью API-шной Windows-функции SetCommBreak. При этом нет необходимости делать интерпретатор идущего по линии потока данных, поскольку интерфейсные команды поступают иным путем.

P.S. Только не забудьте, сразу же закрыть COM-порт (CloseHandle) со стороны компьютера, а после ресета снова его открыть, иначе после ресета USB-порт откажется разговаривать с устройством, позабывшим свой адрес. Т.е. рискуете тем, что устройство перезапустится на bootloader, но USB-канал зависнет в патовой комбинации, из которой выйти можно только вручную - выдернуть и снова воткнуть USB-кабель.

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


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

Вот есть интересная ссылочка USB Developers FAQ: http://www.lvr.com/usbfaq.htm

"How can my application reset, disable, or restart a USB device?

The DevCon example in the Windows DDK is a command-line utility that shows how to enable, disable, restart, update, remove and query devices using the SetupAPI and CfgMgr32 API functions."

Вот этот пример и не получается разжечь!!!

А если SetCommBreak пошлет не моя программа, а какая-нибудь тулза юзера??

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


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

Получилось! :)

Кому интересно: код функции, которая реализует посылку хостом команды Reset устройству.

В качестве параметра в нее передается USB product string descriptor устройства.

 

/////////////////////////////////////////////////////////////////////////////

#include "SetupApi.h"

#pragma comment(lib, "SetupApi")

bool ResetPortDevice(const char *Name);

 

// Name - USB product string descriptor

 

/////////////////////////////////////////////////////////////////////////////

bool ResetPortDevice(const char *Name) {

BOOL bRes;

LPGUID pClassGuidList, piClassGuidList;

DWORD i, j, need_size;

HDEVINFO DeviceInfoSet;

SP_DEVINFO_DATA DeviceInfoData;

SP_PROPCHANGE_PARAMS PropChange;

BYTE *pData;

 

pData = new BYTE[1+strlen(Name)];

if (!pData) return false;

 

// Request number of 'Ports' items

need_size = 0;

pClassGuidList = NULL;

SetupDiClassGuidsFromName("Ports", pClassGuidList, need_size, &need_size);

if (!need_size) {

delete [] pData;

return false;

}

 

// Request all 'Ports' items

piClassGuidList = pClassGuidList = new GUID[need_size];

if (!pClassGuidList) {

delete [] pData;

return false;

}

bRes = SetupDiClassGuidsFromName("Ports", pClassGuidList, need_size, &need_size);

if (!bRes) {

delete [] pData;

delete [] pClassGuidList;

return false;

}

 

// Loop by all GUIDs

for (i = 0; i < need_size; i++, pClassGuidList++) {

 

// Get list of devices

DeviceInfoSet = SetupDiGetClassDevs(pClassGuidList, NULL, NULL, DIGCF_PRESENT);

if (DeviceInfoSet == INVALID_HANDLE_VALUE) continue;

 

DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

PropChange.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);

PropChange.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;

PropChange.StateChange = DICS_PROPCHANGE; // For reset !!!

PropChange.Scope = DICS_FLAG_CONFIGSPECIFIC;

PropChange.HwProfile = 0;

 

// Loop by all devices by given GUID

for (j = 0; SetupDiEnumDeviceInfo(DeviceInfoSet, j, &DeviceInfoData); j++) {

if (GetLastError() == ERROR_NO_MORE_ITEMS) break;

 

// Try get extended information

bRes = SetupDiGetDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, SPDRP_LOCATION_INFORMATION, NULL, pData, 1+strlen(Name), NULL);

if (!bRes) continue;

if (strstr((const char *)pData, Name) == NULL) continue;

 

// Apply function for the found device (i.e. Reset)

bRes = SetupDiSetClassInstallParams(DeviceInfoSet, &DeviceInfoData, &PropChange.ClassInstallHeader, sizeof(PropChange));

if (!bRes) break;

bRes = SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, DeviceInfoSet, &DeviceInfoData);

if (!bRes) break;

}

 

// Clear list of devices

bRes = SetupDiDestroyDeviceInfoList(DeviceInfoSet);

 

if (!bRes) break;

}

 

// Clear arrays

delete [] piClassGuidList;

delete [] pData;

 

if (!bRes) return false;

 

return true;

}

/////////////////////////////////////////////////////////////////////////////

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


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

Получилось! :)

Кому интересно: код функции, которая реализует посылку хостом команды Reset устройству.

 

Ресет USB-устройства и ресет удаленного микропроцессора - вещи совершенно разные! Reset USB-устройства это разрыв логического соединения, а затем его новое соединение с повторным чтением всех дескрипторов и присвоением нового адреса (SET_ADDRESS). Эта процедура происходит на уровне протоколов. Напротив, ресет микроконтроллера означает его физический перезапуск, вследствие чего он имеет возможность запуститься с загрузчика.

Никаким ресетом порта вам не заставить перезапусться микроконтроллер!

 

А если SetCommBreak пошлет не моя программа, а какая-нибудь тулза юзера??

 

Отвечу вам в тон: а что если тулза юзера сделает то же самое, что делает код вашей функции?

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


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

Может я не совсем точно сформулировал сабж.

То что мы хотели, мы получили: микроконтроллер получает стандартную команду от хоста и переходит в бут. Никаких лишних интерпретаций основного протокола.

 

Какова вероятность того что от хоста случайно придет SetCommBreak или несколько байт с правильной CRC(команда)? По-моему второе значительно надежнее.

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


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

Может я не совсем точно сформулировал сабж.

То что мы хотели, мы получили: микроконтроллер получает стандартную команду от хоста и переходит в бут. Никаких лишних интерпретаций основного протокола.

 

Вы сделали программный вызов функции стандартного Class Installer, что соответствует последовательности пунктов меню устройства в Диспетчере устройств Отключить и Задействовать - это не способ перевода устройства в режим загрузчика. Пользователь имеет полное право выбирать эти пункты меню и ... ваше устройство перешло в режим upgrade. Вы предусмотрели выход из такой ситуации?

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


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

Только не забудьте, сразу же закрыть COM-порт (CloseHandle) со стороны компьютера, а после ресета снова его открыть, иначе после ресета USB-порт откажется разговаривать с устройством, позабывшим свой адрес. Т.е. рискуете тем, что устройство перезапустится на bootloader, но USB-канал зависнет в патовой комбинации, из которой выйти можно только вручную - выдернуть и снова воткнуть USB-кабель.

Это все правда. Но для загрузчика можно иметь другой VID/PID, и тогда это будет другой порт.

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


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

Вы сделали программный вызов функции стандартного Class Installer, что соответствует последовательности пунктов меню устройства в Диспетчере устройств Отключить и Задействовать - это не способ перевода устройства в режим загрузчика. Пользователь имеет полное право выбирать эти пункты меню и ... ваше устройство перешло в режим upgrade. Вы предусмотрели выход из такой ситуации?

Юзер может Отключить и Задействовать видеокарту например, это его право. Да устройство перейдет в режим upgrade и выйдет из него через несколько секунд в application не получив команд от PC программы.

Подскажите пожалуйста другое более правильное решение, если знаете. За этим и создан топик.

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

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


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

Юзер может Отключить и Задействовать видеокарту например, это его право. Да устройство перейдет в режим upgrade и выйдет из него через несколько секунд в application не получив команд от PC программы.

Подскажите пожалуйста другое более правильное решение, если знаете. За этим и создан топик.

 

Зачем изобретать велосипед, см.

Device Class Specification for Device Firmware Upgrade

http://www.usb.org/developers/devclass_docs/DFU_1.1.pdf

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


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

Спасибо.

Это то что нужно.

 

Да, если серьезно заинтересованы, то могу выложить продолжение проекта http://projects.caxapa.ru/?ID=45

Он сильно видоизменился.

1. Появился CoInstaller драйвера.

2. Программа загрузки интегрирована в CoInstaller и теперь можно обновлять firmware из Диспетчера устройств.

Вам всего лишь нужно будет реализовать собственно загрузчик в устройстве в соответствии со спецификацией USB класса DFU1.1

3. Появилось API c низко и высокоуровневыми функциями DFU, а также также для работы с DFU файлами. И если не устраивает встроенная

программа загрузки, то можете написать свою, а встроенную отключить. API интегрировано в CoInstaller dll драйвера.

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


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

Мы уже реализовали наш подход. Тестируем на пилотных образцах.

Но в дальнейшем планируем сделать поддержку DFU. Ваш проект несомненно нам интересен.

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


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

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

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

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

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

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

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

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

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

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