STM32 и аппаратный модуль USB
Добавлено: Пн дек 26, 2011 11:14:57
Всем доброе утро!
Стараюсь по возможности не обращаться за помощью, но в этот раз все совсем печально, и мое терпение и силы на исходе. В данный момент разбираюсь с USB микроконтроллера STM32L151 (то же самое, в принципе, что и в мэйнстримовой линейке STM32Fxx). Возникли проблемы с энумерацией.
Итак, по сути. Аппаратно: в линии DP и DM последовательно включил резисторы на 20 Ом. Внешним подтягивающим резистором не пользуюсь, просто при инициализации включаю внутреннюю подтяжку на DP.
Программу писал без использования прерываний, в бесконечном цикле мониторю состояние регистра ISTR, и пляшу исходя из этого.
Путем многочисленных экспериментов удалось установить суть происходящего: 1. Подключаю шнурок к разъему USB своего ноутбука. Хост (точнее, хаб) определяет подключение, дает RESET. Сбрасываюсь. Настраиваю нулевую конечную точку (тип Control, указываю адреса RX и TX-буферов, адрес конечной точки, разрешаю прием). 2. Определяю приход SETUP-пакета, читаю его. По содержимому полей bmRequest и bRequest узнаю, что имеет место запрос GET_DESCRIPTOR, вызываю функцию GetDescriptor (которая определяет тип запрашиваемого дескриптора, и соответствующим образом обрабатывает ситуацию - код чуть ниже). По содержимому старшего байта поля wValue определяю, что хост просит дескриптор устройства (GET_DEVICE_DESCRIPTOR). Полностью содержимое SETUP-пакета имеет вид: 0x80,0x06,0x00,0x01,0x00,0x00,0x40,0x00.
Пытаюсь отправить дескриптор устройства, однако не происходит совершенно ничего. Хост еще раз дает сброс, и ситуация повторяется аналогичным образом. Пощупал линию осциллографом - за все время от включения контроллера и до момента, когда хост дает повторный сброс, появляется пять одинаковых посылок (подозреваю, что это тот самый пакет SETUP). Контроллер же почему-то не отправляет ровным счетом ничего, так получается.. Хотя бит CTR_TX в регистре нулевой конечной точки EP0R устанавливается (это якобы свидетельствует об успешной передаче - хост ответил ACK-"рукопожатием").
Уже совершенно ничего не могу понять - где я допускаю косяк..
На всякий случай (вдруг у кого будет охота глянуть) привожу код обработки запроса GET_DESCRIPTOR.
Все функции, использованные мной - из стандартной библиотеки от ST, грешить на неработоспособность их не приходится. Грешить приходится на собственные кривые ручонки.
Так вот, если кто-нибудь обратил внимание на то, что я что-то делаю неподобающим образом, буду благодарен за комментарии.
Стараюсь по возможности не обращаться за помощью, но в этот раз все совсем печально, и мое терпение и силы на исходе. В данный момент разбираюсь с USB микроконтроллера STM32L151 (то же самое, в принципе, что и в мэйнстримовой линейке STM32Fxx). Возникли проблемы с энумерацией.
Итак, по сути. Аппаратно: в линии DP и DM последовательно включил резисторы на 20 Ом. Внешним подтягивающим резистором не пользуюсь, просто при инициализации включаю внутреннюю подтяжку на DP.
Программу писал без использования прерываний, в бесконечном цикле мониторю состояние регистра ISTR, и пляшу исходя из этого.
Путем многочисленных экспериментов удалось установить суть происходящего: 1. Подключаю шнурок к разъему USB своего ноутбука. Хост (точнее, хаб) определяет подключение, дает RESET. Сбрасываюсь. Настраиваю нулевую конечную точку (тип Control, указываю адреса RX и TX-буферов, адрес конечной точки, разрешаю прием). 2. Определяю приход SETUP-пакета, читаю его. По содержимому полей bmRequest и bRequest узнаю, что имеет место запрос GET_DESCRIPTOR, вызываю функцию GetDescriptor (которая определяет тип запрашиваемого дескриптора, и соответствующим образом обрабатывает ситуацию - код чуть ниже). По содержимому старшего байта поля wValue определяю, что хост просит дескриптор устройства (GET_DEVICE_DESCRIPTOR). Полностью содержимое SETUP-пакета имеет вид: 0x80,0x06,0x00,0x01,0x00,0x00,0x40,0x00.
Пытаюсь отправить дескриптор устройства, однако не происходит совершенно ничего. Хост еще раз дает сброс, и ситуация повторяется аналогичным образом. Пощупал линию осциллографом - за все время от включения контроллера и до момента, когда хост дает повторный сброс, появляется пять одинаковых посылок (подозреваю, что это тот самый пакет SETUP). Контроллер же почему-то не отправляет ровным счетом ничего, так получается.. Хотя бит CTR_TX в регистре нулевой конечной точки EP0R устанавливается (это якобы свидетельствует об успешной передаче - хост ответил ACK-"рукопожатием").
Уже совершенно ничего не могу понять - где я допускаю косяк..
На всякий случай (вдруг у кого будет охота глянуть) привожу код обработки запроса GET_DESCRIPTOR.
Код: Выделить всё
void GetDescriptor(void)
{
u8 Request_Desc;
BYTE data_to_transfer;
uint16_t wLength;
unsigned char zlp;
BYTE *pbuffer;
zlp=FALSE;
Request_Desc = Cam_Bufer[3]; //определяем, какой дескриптор просит хост (в Cam_Bufer[3] - старший байт поля wValue)
switch (Request_Desc)
{
case DEVICE:
{
data_to_transfer = sizeof(usb_device_descriptor);
pbuffer=&(usb_device_descriptor.bLength);
break;
}
case CONFIGURATION:
{
data_to_transfer = sizeof(usb_configuration);
pbuffer = &(usb_configuration.cfg.bLength);
break;
}
}
wLength=ToWord(Cam_Bufer[7],Cam_Bufer[6]); //объединяем в слово байты поля wLength
if (wLength>data_to_transfer) //если длина пакета хоста больше размера дескриптора
{
if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) //и если длина дескриптора делится на макс. размер пакета КТ
{zlp = TRUE;} //то нужно будет послать пакет данных нулевой длины
else
{zlp = FALSE;} // если нет, то пакет нулевой длины не потребуется
}
else
{data_to_transfer=wLength;}
while (data_to_transfer>EP_CONTROL_LENGTH) //пока объем данных для пересылки больше пакета нулевой КТ
{
UserToPMABufferCopy(pbuffer,_GetEPTxAddr(ENDP0),EP_CONTROL_LENGTH); //копируем в PMA 8 байт дескриптора
SetEPTxCount(ENDP0,EP_CONTROL_LENGTH); //устанавливаем счетчик для отправки=8 байт
SetEPTxValid(ENDP0); //разрешаем передачу КТ
pbuffer+=EP_CONTROL_LENGTH; //смещаем указатель на 8
data_to_transfer-=EP_CONTROL_LENGTH; //уменьшаем размер данных к передаче на 8
while (!(USB->USB_EP0R&USB_EP0R_CTR_TX)) {} //ждем, пока не пройдет передача
USB->USB_EP0R &= ~USB_EP0R_CTR_TX; //чистим бит успешной передачи
}
//отсылаем остаточный пакет данных
UserToPMABufferCopy(pbuffer,_GetEPTxAddr(ENDP0),EP_CONTROL_LENGTH);
SetEPTxCount(ENDP0,EP_CONTROL_LENGTH);
SetEPTxValid(ENDP0);
data_to_transfer=0;
while (!(USB->USB_EP0R&USB_EP0R_CTR_TX)) {}
USB->USB_EP0R &= ~USB_EP0R_CTR_TX;
//если требуется пакет данных нулевой длины, то отправляем его
if (zlp==TRUE)
{
Send0LengthData();
while (!(USB->USB_EP0R&USB_EP0R_CTR_TX)){}
USB->USB_EP0R &= ~USB_EP0R_CTR_TX;
}
//разрешаем прием нулевой КТ
SetEPRxCount(ENDP0,8);
SetEPRxStatus(ENDP0,EP_RX_VALID);
return;
}
Так вот, если кто-нибудь обратил внимание на то, что я что-то делаю неподобающим образом, буду благодарен за комментарии.


