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

 
 
10 страниц V   1 2 3 > »   
Reply to this topicStart new topic
> STM32 USB FS OTG
V_M_Luck
сообщение Jul 8 2011, 13:24
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 26-11-05
Пользователь №: 11 420



Разбираюсь с USB FS OTG на STM32F107. Есть плата с STM32F107 и USB. Мне нужен только device. Что то самостоятельно по даташиту не очень получилось. Попытался запустить пример HID от ST из STM32_USB-FS-Device_Lib_V3.3.0. Не работает. Попадает пару раз в прерывание по RESET, потом в ENUMDN и все. Больше никакой активности.
Смотрел USB TRACE - host даже не пытается запрашивать дескрипторы.
Вопрос - у кого-нибудь этот пример заработал?

Извините. Нашел у себя косяк - пример заработал.

Сообщение отредактировал V_M_Luck - Jul 8 2011, 15:32
Go to the top of the page
 
+Quote Post
V_M_Luck
сообщение Jul 13 2011, 15:51
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 26-11-05
Пользователь №: 11 420



Вновь поднимаю тему.
Пример-то заработал. Но тянуть к себе в проект дикий фреймворк из-за одного эндпоинта для HID совсем не хочется. Стал разбираться в регистрах по даташиту и примеру.
Инициализацию вроде-бы сделал. Получаю USBRST, ENUMDNE, потом получаю запрос GET_DEVICE_DESCRIPTOR.
И тут-то все начинается. Настраиваю DIEPTSIZ0, DIEPCTL0 .
Помещаю в фифо данные.
Получаю прерывание на IN endpoint XFRCM. Вроде все ОК. Но HOST этого дескриптора не видит. В результате, вместо SET_ADDRESS опять получаю GET_DEVICE_DESCRIPTOR и все по кругу. Так раз 5 и HOST прекращает енумерацию.

Уже два дня голову ломаю. Может кто-нибудь сталкивался? Подскажите, в какую сторону посмотреть.
Go to the top of the page
 
+Quote Post
SviMik
сообщение Sep 9 2012, 11:41
Сообщение #3





Группа: Участник
Сообщений: 11
Регистрация: 9-09-12
Пользователь №: 73 458



Ровно та же проблема, как и в последнем сообщении. XFRCM прерывание получаю, от компа на дескриптор ноль реакции.
Дескриптор заведомо рабочий, взят из проекта, который делал на МК другого производителя.
Пробовал делать как строго по даташиту, так и переставлять всё, что только возможно - не работает.

Если автор решил проблему - хотелось бы узнать как sm.gif
Go to the top of the page
 
+Quote Post
Forger
сообщение Sep 9 2012, 15:07
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 629
Регистрация: 22-02-05
Пользователь №: 2 831



Цитата(V_M_Luck @ Jul 13 2011, 19:51) *
...Подскажите, в какую сторону посмотреть...

Попробуте все ваши дискрипторы вставить в заведомо рабочий проект, пусть даже с "толстым" фреймворком.
Далее можно просто записать все, что отправляется/принимается хостом (соот. прогой) и сравнивать уже с логами уже своего проекта.
Наверняка, будет в чем-то разница, оттуда и копать sm.gif
Go to the top of the page
 
+Quote Post
SviMik
сообщение Sep 9 2012, 16:10
Сообщение #5





Группа: Участник
Сообщений: 11
Регистрация: 9-09-12
Пользователь №: 73 458



В моём случае, дескриптор взят из заведомо рабочего проекта, но под другой МК (ARM от атмела, ATSAM3S). Там я писал полностью сам, без библиотек, так что в протоколе USB немного понимаю (как мне кажется).

Решил пересесть на STM, и вот такой затык.

Цитата
Далее можно просто записать все, что отправляется/принимается хостом (соот. прогой)

К сожалению, не всё. Я пробовал SniffUSB, но он начинает запись только после корректного опознания устройства, тоесть абсолютно бесполезен в моём случае.

Мой текущий дескриптор девайса выглядит так (как я уже сказал, он заведомо рабочий):
Код
static char device_descriptor[18]={
    /* Standard USB device descriptor for the CDC serial driver */
    sizeof(device_descriptor), // size
    1, // USBGenericDescriptor_DEVICE
    0x00,0x02, // USBDeviceDescriptor_USB2_00
    2, // CDCDeviceDescriptor_CLASS
    0, // CDCDeviceDescriptor_SUBCLASS
    0, // CDCDeviceDescriptor_PROTOCOL
    64, // BOARD_USB_ENDPOINTS_MAXPACKETSIZE
    0xEB,0x03, // CDCDSerialDriverDescriptors_VENDORID
    0x24,0x61, // CDCDSerialDriverDescriptors_PRODUCTID
    0x10,0x01, // CDCDSerialDriverDescriptors_RELEASE
    1, // Index of manufacturer description //0
    2, // Index of product description //0
    3, // Index of serial number description //0
    1, // One possible configuration
};

(остальные не привожу, т.к. до них вообще дело не доходит)

Что происходит на заведомо рабочей плате с SAM3S:
1. usb сброс
2. приходит setup пакет с запросом дескриптора девайса
3. МК отправляет дескриптор (18 байт)
4. usb сброс
5. приходит фрейм, назначающий адрес usb устройству
6. и т.д.

Что происходит с STM32F4: не работает.
1. usb сброс
2. приходит setup пакет с запросом дескриптора девайса
3. МК отправляет дескриптор (18 байт)
4. а дальше тишина, и через 3 секунды переходим к п.1

Приблизительный код для стм32 (упрощено до безобразия в целях отладки):
Код
volatile uint32_t * fifo=(uint32_t *)(OTG_FS_DFIFO0_BASE);
OTG_FS->DIEPTSIZ0=(1<<19)|18; // PKTCNT; XFRSIZ
OTG_FS->DIEPCTL0=(1<<31)|(1<<26); // EPENA; CNAK
*fifo=0x02000112;
*fifo=0x40000002;
*fifo=0x612403EB;
*fifo=0x02010110;
*fifo=0x00000103;


Работу с FIFO предполагаю, на основе того, что чтение работает таким образом:
Код
volatile uint32_t * fifo=(uint32_t *)OTG_FS_DFIFO0_BASE;
int i=0;
for(i=0;i<BCNT;i+=4){
    int data=*fifo;
    rbuf[i+0]=(data>>0)&0xFF;
    rbuf[i+1]=(data>>8)&0xFF;
    rbuf[i+2]=(data>>16)&0xFF;
    rbuf[i+3]=(data>>24)&0xFF;
    pprintf("< %02X%02X%02X%02X", rbuf[i+0], rbuf[i+1], rbuf[i+2], rbuf[i+3]);
}


Исходя из даташита, я делаю правильно.

1. DIEPTSIZ0 должен устанавливаться до того, как поставлю EPENA в DIEPCTL0
Цитата
The application must modify this register before enabling endpoint 0. Once endpoint 0 is
enabled using the endpoint enable bit in the device control endpoint 0 control registers
(EPENA in OTG_FS_DIEPCTL0), the core modifies this register. The application can only
read this register


2. EPENA в DIEPCTL0 должен устанавливаться до того, как начну писать данные в FIFO.
Цитата
1. Program the OTG_FS_DIEPCTLx register with the endpoint characteristics and set the
CNAK and EPENA bits.
2. Write the data to be transmitted in the next frame to the transmit FIFO.


Цитата
1. The application must set the transfer size and packet count fields in the endpointspecific
registers and enable the endpoint to transmit the data.
2. The application must also write the required data to the transmit FIFO for the endpoint.


Однако, я пробовал и другой порядок действий, безрезультатно.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Sep 9 2012, 19:54
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 10 117
Регистрация: 11-12-04
Пользователь №: 1 448



CNAK в DOEPCTL0 после обработки setup установить не забыли?
Go to the top of the page
 
+Quote Post
SviMik
сообщение Sep 9 2012, 22:19
Сообщение #7





Группа: Участник
Сообщений: 11
Регистрация: 9-09-12
Пользователь №: 73 458



Вот же однако... Заработало! Плюс вам в карму, если б она тут была sm.gif
А я CNAK только один раз при инициализации ставил, и думал оно так и будет...

Интересно, а когда "по правилам" его надо ставить? "после обработки setup" это когда
1. закончил приём setup запроса
2. только записал ответ на setup в FIFO
3. когда отправка моего ответа уже завершена

(сейчас я поставил от балды)
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Sep 9 2012, 22:51
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 10 117
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(SviMik @ Sep 10 2012, 02:19) *
Интересно, а когда "по правилам" его надо ставить? "после обработки setup" это когда
1. закончил приём setup запроса
2. только записал ответ на setup в FIFO
3. когда отправка моего ответа уже завершена

В общем-то в любой момент правильно, можно после п.1
Go to the top of the page
 
+Quote Post
SviMik
сообщение Sep 17 2012, 00:32
Сообщение #9





Группа: Участник
Сообщений: 11
Регистрация: 9-09-12
Пользователь №: 73 458



Пытаюсь реализовать CDC девайс. Что получилось:
1. Приём от компа к девайсу - без проблем, любое количество данных.
2. Отправка от девайса к компу - отправляется только первый пакет. Дальше ничего не шлётся.

Что я мог упустить?

Код
void hwtx(){
    volatile uint32_t * fifo=(uint32_t *)OTG_FS_DFIFO2_BASE;
    int i;
    int len=12;
    char data[]={"Hello world\n"};
    pprintf("1. FIFO: %i words free", OTG_FS->DTXFSTS2&0xFFFF);
    OTG_FS->DIEPTSIZ2=(1<<19)|(len<<0); // PKTCNT; XFRSIZ
    OTG_FS->DIEPCTL2|=(1UL<<31)|(1<<26); // EPENA; CNAK
    for(i=0;i<len;i+=4){
        *fifo=((data[i+0]&0xFF)<<0)|((data[i+1]&0xFF)<<8)|((data[i+2]&0xFF)<<16)|((data[i+3]&0xFF)<<24);
    }
    pprintf("2. FIFO: %i words free", OTG_FS->DTXFSTS2&0xFFFF);
}


попытка 1, строка приходит
1. FIFO: 64 words free
2. FIFO: 61 words free
IRQ: SOF
IRQ: EP2 IN XFRC (Transfer completed)

попытка 2:
1. FIFO: 64 words free
2. FIFO: 61 words free

попытка 3:
1. FIFO: 61 words free
2. FIFO: 58 words free

тоесть далее просто забивается FIFO, а отправка не идёт...

Сообщение отредактировал SviMik - Sep 17 2012, 00:35
Go to the top of the page
 
+Quote Post
SviMik
сообщение Sep 18 2012, 00:11
Сообщение #10





Группа: Участник
Сообщений: 11
Регистрация: 9-09-12
Пользователь №: 73 458



Вомзжно, я что-то не так понял с FIFO буфферами. Если верить даташиту, размер буффера указывается в word, т.е. по 4 байта.
Текущая инициализация FIFO выглядит так:
Код
OTG_FS->GRXFSIZ=64; // RX FIFO = x words
OTG_FS->DIEPTXF0=(128<<16) | 64; // TX FIFO 0 = x words; start=x
OTG_FS->DIEPTXF1=(64<<16) | 192; // TX FIFO 1 = x words; start=x
OTG_FS->DIEPTXF2=(64<<16) | 256; // TX FIFO 2 = x words; start=x


Это конфигурация, при которой девайс нормально инициализируется. При попытке уменьшить приёмный буффер, инициализация уже не проходит. Хотя 64 cлова (256 байт) явно избыточно для SETUP пакетов.

Инициализация эндпоинтов:

Код
/* CDC endpoints: 0:control, 1:bulk out, 2:bulk in, 3:int in */
/* OUT */
OTG_FS->DOEPCTL0=(1<<26)|(1<<15)|(0<<0); // CNAK; active endpoint; Maximum packet size=64;
OTG_FS->DOEPCTL1=(1<<26)|(2<<18)|(1<<15)|(64<<0); // CNAK; Endpoint type; active endpoint; Maximum packet size;
/* IN */
OTG_FS->DIEPCTL0=(0<<22)|(1<<15)|(0<<0); // TxFIFO number; active endpoint; Maximum packet size=64;
OTG_FS->DIEPCTL2=(2<<22)|(2<<18)|(1<<15)|(64<<0); // TxFIFO number; Endpoint type; active endpoint; Maximum packet size;
Go to the top of the page
 
+Quote Post
MBR
сообщение Sep 18 2012, 10:49
Сообщение #11


Частый гость
**

Группа: Участник
Сообщений: 107
Регистрация: 26-09-10
Пользователь №: 59 748



Цитата(SviMik @ Sep 18 2012, 04:11) *
Это конфигурация, при которой девайс нормально инициализируется.

receive fifo шареный. Он не только для setup-пакетов используется. Плюсом, не забываете DIEPTXFx offset сдвигать при уменьшении GRXFSIZ?

Еще чтение мануалов рулит:

10 locations must be reserved in the receive FIFO to receive SETUP packets on control
endpoint. The core does not use these locations, which are reserved for SETUP packets, to
write any other data. One location is to be allocated for Global OUT NAK. Status information
is written to the FIFO along with each received packet. Therefore, a minimum space of
(Largest Packet Size / 4) + 1 must be allocated to receive packets. If multiple isochronous
endpoints are enabled, then at least two (Largest Packet Size / 4) + 1 spaces must be
allocated to receive back-to-back packets. Typically, two (Largest Packet Size / 4) + 1
spaces are recommended so that when the previous packet is being transferred to the CPU,
the USB can receive the subsequent packet.

От себя добавлю, что рекомендация two (Largest Packet Size / 4) + 1 исходит из того, что, пока мы один буфер из FIFO забираем, железо уже принимает второй.

Сообщение отредактировал MBR - Sep 18 2012, 10:54
Go to the top of the page
 
+Quote Post
SviMik
сообщение Sep 18 2012, 13:48
Сообщение #12





Группа: Участник
Сообщений: 11
Регистрация: 9-09-12
Пользователь №: 73 458



Хорошо. Тоесть моя конфигурация выше впринципе правильная, и должна работать? Но почему же с отправкой у меня проблемы... При этом, в нулевой эндпоинт отправлять дескрипторы проблем нет, а отправить данные в второй эндпоинт - проходит только первый пакет и всё. Возможно, с bulk эндпоинтами как-то иначе поступать надо?

А документация уже утомила своими ляпами... В таблице одно, в тексте другое... Доходит до того, что в таблице бит подписан Reserved, а ниже в тексте даётся его нормальное описание. Или в таблице "r", а в описании сказано, что в него писать надо. IN и OUT тоже путают, приходится логически до всего доходить. Даже ссылки неправильные. кликаю в оглавлении на DIEPTSIZx, попадаю на DOEPTSIZx... такой вот тест на внимательность sad.gif
Извиняюсь, накипело...
Go to the top of the page
 
+Quote Post
MBR
сообщение Sep 18 2012, 14:05
Сообщение #13


Частый гость
**

Группа: Участник
Сообщений: 107
Регистрация: 26-09-10
Пользователь №: 59 748



Цитата(SviMik @ Sep 18 2012, 17:48) *
При этом, в нулевой эндпоинт отправлять дескрипторы проблем нет, а отправить данные в второй эндпоинт - проходит только первый пакет и всё. Возможно, с bulk эндпоинтами как-то иначе поступать надо?

А XFRC не забываете сбрасывать после приема пакета?
Go to the top of the page
 
+Quote Post
SviMik
сообщение Sep 18 2012, 14:27
Сообщение #14





Группа: Участник
Сообщений: 11
Регистрация: 9-09-12
Пользователь №: 73 458



Всмысле флаг прерывания? Да, как и все остальные прерывания, сбрасываю.

Код
    }else if(OTG_FS->DAINT&(1<<2)){ // IEPINT on EP 2
        //print("- DAINT_IRQ: EP2 IN");
        if(OTG_FS->DIEPINT2&(1<<0)){ // Data IN transaction completed
            OTG_FS->DIEPINT2=(1<<0);
            pprintf("EP_IRQ(IN): EP2 XFRC");
        }else if(OTG_FS->DIEPINT2&(1<<1)){ // Endpoint disabled interrupt
            OTG_FS->DIEPINT2=(1<<1);
            pprintf("EP_IRQ(IN): EP2 EPDISD");
        }else if(OTG_FS->DIEPINT2&(1<<3)){ // Timeout condition mask
            OTG_FS->DIEPINT2=(1<<3);
            pprintf("EP_IRQ(IN): EP2 TOC");
        }else if(OTG_FS->DIEPINT2&(1<<4)){ // IN token received when TxFIFO is empty
            OTG_FS->DIEPINT2=(1<<4);
            pprintf("EP_IRQ(IN): EP2 ITTXFE");
        }else if(OTG_FS->DIEPINT2&(1<<6)){ // IN endpoint NAK effective
            OTG_FS->DIEPINT2=(1<<6);
            pprintf("EP_IRQ(IN): EP2 INEPNE");
        }else if(OTG_FS->DIEPINT2&(1<<7)){ // Transmit FIFO empty
            OTG_FS->DIEPINT2=(1<<7);
            pprintf("EP_IRQ(IN): EP2 TXFE");
        }else{
            pprintf("EP_IRQ(IN): EP2 %i", OTG_FS->DIEPINT2);
        }
    }
Go to the top of the page
 
+Quote Post
MBR
сообщение Sep 18 2012, 15:03
Сообщение #15


Частый гость
**

Группа: Участник
Сообщений: 107
Регистрация: 26-09-10
Пользователь №: 59 748



А где запись данных после отправки очередного балка?
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 17th August 2017 - 17:36
Рейтинг@Mail.ru


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