Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: USB - AT91SAM7A3
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
shrek
Суть проблемы состоит в том что, (слава всем Святым удалось сконфигурировать данный девайс, запустить ФАПЧ на 96 МГц, контроллер прерываний!!! и прочие нужные настройки, обеспечивающие нормальное функционирование контроллера) когда я на этой платке подключаю (благо есть возможность) с помощью ноги PB1 резистор подтягивающий шину D+ к +3,3 вольтам комп мне присылает запрос в виде набора байтов.
Конкретно 80 06 00 01 00 00 40 00 3E FC C3 0D C1 B8 69 2E.
Возникает вопрос как обработать данную последовательность байтов?...
Обратился к источнику "Агуров Интерфейс USB практика использования и программирования".
показалось что 8006 - это запрос дескриптора устройства, а 0001 - это что то связанное с очисткой девайся USB контроллера...
А остальные байты?... непонятно... В скачанной спецификации USB с офсайта не нашел или плохо искал... По крайней мере мне так показалось что там этого нет...
Вот и прошу помощи) Уважаемые Гуру форума направте пожалуйста на нужные источники для успешного освоения девайса USB и протокола USB)
Заранее спасибо)
mempfis_
Цитата(shrek @ Jan 29 2009, 17:17) *
Конкретно 80 06 00 01 00 00 40 00 3E FC C3 0D C1 B8 69 2E.
Возникает вопрос как обработать данную последовательность байтов?...
Обратился к источнику "Агуров Интерфейс USB практика использования и программирования".
показалось что 8006 - это запрос дескриптора устройства, а 0001 - это что то связанное с очисткой девайся USB контроллера...
А остальные байты?... непонятно... В скачанной спецификации USB с офсайта не нашел или плохо искал... По крайней мере мне так показалось что там этого нет...


В спецификации всё это описано. И в Агурове тоже.
Из всего вашего набора байт запрос только первые 8.
Запросы состоят из стандартных полей по 2 байта
wRequest wValue wIndex wLenth
Процесс энумерации на шине состоит из запроса дескрипторов. Первый который приходит GET_DESCRIPTOR_DEVICE wRequest = 0x8006
Это стандартный запрос от хост-контроллера (ещё бывают запросы класса).
Далее идёт тип запрашиваемого дескриптора. Их много, вот некоторые из них:
Код
#define device           0x0100
#define configuration           0x0200
#define string_language       0x0300
#define string_manufacture  0x0301
#define string_product         0x0302
#define string_sn                 0x0303
#define interface                 0x0400


Для чего нужно поле wIndex точно не помню.
Поле wLenth - кол-во запрашиваемых байт.

Поищите в спецификации эти поля и всё станет ясно. Как найду выложу довольно полезную книгу где все эти запросы расписаны на довольно понятном английском языке smile.gif
shrek
Спасибо за ответ)
Я вчера тоже понял в чем суть первых восьми байт)
Но непонятки на счет вторых восьми байт остаются...
и поле wLenght = 40 00 что оно может означать?... В спецификации это число байт для передачи... куда?... 4000 это 16 килобайт)))

Как пишет Агуров 00 01 это есть wValue
но... старший байт это есть тип дескриптора... то есть 01 - Стандартный дескриптор устройства... но почему то он на месте младшего байта...
я все посылки писал в массив и первые 8 байт стабильно 80 06 00 01 00 00 40 00 ничего больше
Zayac
Для атмела существуют примеры кода по работе с USB, их можно переделать под свои нужны. На это наверное уйдет меньше времени, чем на написание стека USB полностью с нуля
mempfis_
Цитата(shrek @ Jan 30 2009, 10:51) *
Спасибо за ответ)
Я вчера тоже понял в чем суть первых восьми байт)
Но непонятки на счет вторых восьми байт остаются...
и поле wLenght = 40 00 что оно может означать?... В спецификации это число байт для передачи... куда?... 4000 это 16 килобайт)))

Как пишет Агуров 00 01 это есть wValue
но... старший байт это есть тип дескриптора... то есть 01 - Стандартный дескриптор устройства... но почему то он на месте младшего байта...
я все посылки писал в массив и первые 8 байт стабильно 80 06 00 01 00 00 40 00 ничего больше


Поля bmRequestType и bRequest однобайтные.
Все остальные поля двухбайтные. Я уже точно не помню но кажется по спецификации при двухбайтных параметрах сначала передаётся младший байт потом старший (отсюда и получается wLenght = 40 00 = low byte:high byte т.е. длина = 0040h = 64 байта)
Посмотрите приложенную книгу - я по ней когдато разбирался со стандартными запросами. Там всё коротко и довольно понятно. Все неясные моменты лучше смотреть в спецификации.
Создайте по этой книге вот такой дескриптор устройства:

Код
//Структура дескриптора устройства
/* Global constant structure located in FLASH */
flash struct st_usb_device_descriptor  
{
int bLenth;             //длина дескриптора
int bDescriptorType;    //тип дескриптора
int bcdUSBL;             //версия спецификации USB в формате BCD
int bcdUSBH;             //версия спецификации USB в формате BCD
int bDeviceClass;       //код класса устройства USB
int bDeviceSubclass;    //код подкласса устройства USB
int bDeviceProtocol;    //код протокола USB
int bMaxPacketSize0;    //мах размер нулевой конечной точки
int idVendorL;            //идентификатор изготовителя устройства
int idVendorH;            //идентификатор изготовителя устройства
int idProductL;           //идентификатор продукта
int idProductH;           //идентификатор продукта
int bcdDeviceL;          //номер версии устройства в формате BCD
int bcdDeviceH;          //номер версии устройства в формате BCD
int iManufacture;       //индекс дескриптора строки описывающей  изготовителя
int iProduct;           //индекс дескриптора строки описывающей  продукт
int iSerialNumber;      //индекс дескриптора строки описывающей  серийный номер устройства
int bNumConfigurations; //количество возможных конфигураций устройства
};


Попробуйте отослать его и дождатся следующего запроса SET_ADDRESS 0x0005
shrek
В общем вопрос еще такой возник...
Вот этот дескриптор устройства надо отправлять через нулевую конечную точку или через какую нить другую настроенную на работу IN по проерыванию или что то там еще?
Или же через нулевую? Дескриптор устройства 18 байт размер буфера нулевой точки 8 байт за раз не отправишь...
aaarrr
Цитата(shrek @ Feb 10 2009, 12:53) *
Или же через нулевую? Дескриптор устройства 18 байт размер буфера нулевой точки 8 байт за раз не отправишь...

Через нулевую. Дескриптор длиной 18 байт передается в трех пакетах. Если размер дескриптора кратен размеру буфера, в конце надо отправить пакет нулевой длины.
shrek
после отправки каждого пакета по идее от хоста должно следовать подтверждение приема?
и после отправки дескриптора хост должен прислать запрос установки адреса?
У девайса есть такое прерывание SOFINT по началу фрейма не подскажите как его обработать?
в принципе вся обработка запрос USB у меня построено на обработке прерываний
и еще непонятно вроде я запретил все прерывания кроме прерываний конечных точек и непонятно почему арм постоянно входит в обработку прерываний...
aaarrr
Цитата(shrek @ Feb 10 2009, 15:55) *
после отправки каждого пакета по идее от хоста должно следовать подтверждение приема?

Да, Вы в результате получите прерывание TXCOMP, Дальше отправляете хосту следующий пакет, пакет нулевой длины, или просто сбрасываете TXCOMP, в зависимости от обстоятельств.

Цитата(shrek @ Feb 10 2009, 15:55) *
и после отправки дескриптора хост должен прислать запрос установки адреса?

Должен, если с дескриптором все в порядке.

Цитата(shrek @ Feb 10 2009, 15:55) *
У девайса есть такое прерывание SOFINT по началу фрейма не подскажите как его обработать?

Можете никак не обрабатывать, если не нужно.

Цитата(shrek @ Feb 10 2009, 15:55) *
и еще непонятно вроде я запретил все прерывания кроме прерываний конечных точек и непонятно почему арм постоянно входит в обработку прерываний...

Прерывание ENDBUSRES не отключается в принципе.
shrek
То есть получается использовать USB девайс и при этом выполнять что то в режиме USER (например математику какую нибудь) не получится я так понимаю (кроме случая когда в контроллере прерываний запрещаю USB прерывания) ?

и еще вопрос...
Если я в буфер приемопередатчика пишу не 8 байт, а как в примере с дескриптором устройства оставшиеся 2 байта, еще необходимо 6 байт нулей записывать или нет?
aaarrr
Почему? Просто обрабатывайте BUSRES как надо.
shrek
Вроде бы девайс аппаратно обрабатывает сброс?...
при чтении этот бит не сбрасывается
получается что арм постоянно в прерывании находится и возможности втиснуть обработку в основную часть программы нет... кроме как непосредственно в прерывание...
aaarrr
Цитата(shrek @ Feb 10 2009, 17:21) *
при чтении этот бит не сбрасывается

Так сбросьте его записью в UDP_ICR.
shrek
МММ... В книжке Редькина этого бита нет в регистре UDP_ICR...
или это опечатка?
я собственно поэтому и спрашиваю)

Каюсь родной даташит не смотрел по этой теме)))
aaarrr
Цитата(shrek @ Feb 10 2009, 17:30) *
МММ... В книжке Редькина этого бита нет в регистре UDP_ICR...

Книжке Редькина место в помойке. Возьмите даташит.
shrek
ну не совсем в помойке)
да в даташите этот бит в регистре присутствует)
aaarrr
Цитата(shrek @ Feb 10 2009, 17:37) *
ну не совсем в помойке)

Именно там, в лучшем случае на пункте приема макулатуры. Неоднократно обсуждались на форуме его творения. Сказать, что качество "материала" отвратительное - это ничего не сказать.
shrek
Все-таки непонятна работа USB девайса
Я запрещаю все прерывания
Код
AT91C_BASE_UDP  -> UDP_IDR     =  AT91C_UDP_ALL_INT;//Запрещаем все прерывания

Сбрасываю все прерывания, которые можно сбросить
Код
AT91C_BASE_UDP  -> UDP_ICR     =  AT91C_UDP_CLEAR_INT;//Сброс прерываний

разрешаю прерывания только для 0 конечной точки
Код
AT91C_BASE_UDP  -> UDP_IER     =  AT91C_UDP_EPINT0;//Разрешить прерывание от 0 конечной точки

в обработчике прерываний если поступил сброс шины сбрасываю прерывание
Код
if ((AT91C_BASE_UDP -> UDP_ISR) & AT91C_UDP_ENDBUSRES)
          {
          while (!((AT91C_BASE_US0 -> US_CSR) & AT91C_US_TXRDY));
          AT91C_BASE_US0  -> US_THR = 0xF4;//это для отладки шлю в ком порт инфу что именно это прерывание обработанно
          AT91C_BASE_UDP -> UDP_ICR |= AT91C_UDP_ENDBUSRES;
          }

и все равно ядро постоянно обрабатывает прерывание!!
фактически постоянно в нем висит...
?????
aaarrr
Цитата(shrek @ Feb 19 2009, 11:24) *
и все равно ядро постоянно обрабатывает прерывание!!
фактически постоянно в нем висит...
?????

Правильно будет написать так:
Код
AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_ENDBUSRES;


Вы учитываете, что BUS_RESET действительно сбрасывает модуль UDP?

Цитата
Once the ENDBUSRES interrupt has been triggered, the device enters Default State. In this
state, the UDP software must:
• Enable the default endpoint, setting the EPEDS flag in the UDP_CSR[0] register and,
optionally, enabling the interrupt for endpoint 0 by writing 1 to the UDP_IER register. The
enumeration then begins by a control transfer.
• Configure the interrupt mask register which has been reset by the USB reset detection
• Enable the transceiver clearing the TXVDIS flag in the UDP_TXVC register.
In this state UDPCK and MCK must be enabled.
Warning: Each time an ENDBUSRES interrupt is triggered, the Interrupt Mask Register and
UDP_CSR registers have been reset.
shrek
А вот этого я как раз и не учитывал....

то есть фактический после каждого сброса шины мне заново необходимо сконфигурировать мое устройство?)
aaarrr
Цитата(shrek @ Feb 19 2009, 12:47) *
то есть фактический после каждого сброса шины мне заново необходимо сконфигурировать мое устройство?)

Да, то есть по сбросу шины и имеет смысл конфигурировать прерывания и нулевую точку.
shrek
будем пробовать по тому как что то получается)
Спасибо за очень ценный совет!
shrek
Кое что выяснилось...
После, как ни странно, трех сбросов шины) обработчику прерываний все таки удается принять управляющий пакет)
выяснил что прерывание поступает от нулевой конечной точки...
дальше пытаюсь выяснить от чего же поступило прерывание...
прерывание поступает по принятию пакета управления...
питаюсь прочитать его из буфера... и вот тут то проблема...
контроллер говорит мне ( по самопально организованному через USART0 порту отладки :-) ) что в буфере 0 байт...
???
могу причести листинг моего обработчика прерываний
Код
#include "ioat91sam7a3.h"

#define UP        0x00000200
#define LEFT      0x00002000
#define DOWN      0x00000100
#define RIGHT     0x00001000
#define BUTTON    0x00004000
#define LED_1     0x00100000
#define LED_2     0x00200000
#define LED_3     0x01000000
#define LED_4     0x02000000

//---Коды стандартных запросов (bRequest)---------------------------------------
#define GET_STATUS        0x00           //Запрос статуса
#define CLEAR_FEATURE     0x01           //Сброс устройства
#define SET_FEATURE       0x03           //Установить устройство
#define SET_ADRESS        0x05           //Установить адрес
#define GET_DESCRIPTOR    0x06           //Получить дескриптор
#define SET_DESCRIPTOR    0x07           //Загрузить дескриптор
#define GET_CONFIGURATION 0x08           //Получить код текущей конфигурации
#define SET_CONFIGURATION 0x09           //Установить конфигурацию
#define GET_INTERFACE     0x0A           //Получить код интерфейса
#define SET_INTERFACE     0x0B           //Установить интерфейс
#define SYNC_FRAME        0x0C           //Кадр синхронизации

//---Структура управляющего пакета----------------------------------------------
struct TSetupPacket
     {
     unsigned char bmRequestType;        //Тип запроса
     unsigned char bRequest;             //Код запроса
     unsigned char ValueL;               //Тип дескриптора
     unsigned char ValueH;               //Индекс дескриптора
     unsigned char IndexL;               //Номер интерфейса или конечной точки
     unsigned char IndexH;               //Номер интерфейса или конечной точки
     unsigned char LengthL;              //Число байт для передачи
     unsigned char LengthH;              //Число байт для передачи
     } TSetupPacket;

//---Структура дескриптора устройства-------------------------------------------
const struct USB_DEVICE_DESCRIPTOR
     {
     unsigned char bLenth;               //длина дескриптора
     unsigned char bDescriptorType;      //тип дескриптора
     unsigned char bcdUSBL;              //версия спецификации USB в формате BCD
     unsigned char bcdUSBH;              //версия спецификации USB в формате BCD
     unsigned char bDeviceClass;         //код класса устройства USB
     unsigned char bDeviceSubclass;      //код подкласса устройства USB
     unsigned char bDeviceProtocol;      //код протокола USB
     unsigned char bMaxPacketSize0;      //мах размер нулевой конечной точки
     unsigned char idVendorL;            //идентификатор изготовителя устройства
     unsigned char idVendorH;            //идентификатор изготовителя устройства
     unsigned char idProductL;           //идентификатор продукта
     unsigned char idProductH;           //идентификатор продукта
     unsigned char bcdDeviceL;           //номер версии устройства в формате BCD
     unsigned char bcdDeviceH;           //номер версии устройства в формате BCD
     unsigned char iManufacture;         //индекс дескриптора строки описывающей  изготовителя
     unsigned char iProduct;             //индекс дескриптора строки описывающей  продукт
     unsigned char iSerialNumber;        //индекс дескриптора строки описывающей  серийный номер устройства
     unsigned char bNumConfigurations;   //количество возможных конфигураций устройства
     } USB_DEVICE_DESCRIPTOR = {0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08, 0x14, 0x11, 0x77, 0x77, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x01};

//------------------------------------------------------------------------------
const unsigned short int   BUFFER_SIZE_EP[6] = {0x08, 0x40, 0x40, 0x40, 0x100, 0x100};//размер буфера конечных точек
      unsigned short int   i = 0;                                                     //индикатор конечной точки по умолчанию 0
      unsigned short int   COUNT;                                                     //счетчик байтов при загрузке в буфер или сохранинии из буфера
      unsigned short int   RX_BYTE_COUNT;                                             //колво байтов в буфере приемника
      unsigned short int   TX_BYTE_COUNT;                                             //колво байтов для передачи
      unsigned char       *DATA_OUT_ADRESS;                                           //указатель на сегмент памяти, содержащий данные для сохранения в буфер приемопередатчика
      unsigned char       *DATA_IN_ADRESS;                                            //указатель на сегмент памяти, содержащий сохраненные данные из буфера приемопередатчика


//==============================================================================
//---Блок выгрузки данных в буфер FIFO UDP_FDR[i]-------------------------------
void USB_TRANSMIT_EP()                                                          //Функция блока сохранения данных в буфер конечной точки 0
     {
     while ((AT91C_BASE_UDP -> UDP_CSR[i]) & AT91C_UDP_TXPKTRDY);               //ждать пока бит AT91C_UDP_TXPKTRDY станет 0
     COUNT = 0;                                                                 //обнуляем счетчик байтов
     while (COUNT < BUFFER_SIZE_EP[i])                                          //запускаем цикл загрузки байтов в буфер i-ой конечной точки
           {
           if (TX_BYTE_COUNT > 0)
                {
                AT91C_BASE_UDP -> UDP_FDR[i] = *DATA_OUT_ADRESS;                //загружаем байт в буфер
                COUNT++;                                                        //инкрементируем счетчик байтов
                TX_BYTE_COUNT--;                                                //декрементируем счетчик отправленных байтов
                DATA_OUT_ADRESS++;                                              //инкрементируем адрес для записи в буфер следующего байта
                }
           else
                {
                AT91C_BASE_UDP -> UDP_FDR[i] = 0x00;                            //Добисываем оставшиеся нули
                COUNT++;                                                        //инкрементируем счетчик байтов
                }
           }
     AT91C_BASE_UDP -> UDP_CSR[i] |= AT91C_UDP_TXPKTRDY;                        //установка бита готовности пакета к передаче
     }
//==============================================================================



//==============================================================================
//---Блок загрузки данных из буфера FIFO UDP_FDR[i]-----------------------------
void USB_RECEIVE_EP()                                                           //Функция блока сохранения данных из буфера конечной точки 0
     {
     RX_BYTE_COUNT = (((AT91C_BASE_UDP -> UDP_CSR[i]) & AT91C_UDP_RXBYTECNT) >> 16);//число байтов в буфере
     while (!((AT91C_BASE_US0 -> US_CSR) & AT91C_US_TXRDY));
     AT91C_BASE_US0  -> US_THR = RX_BYTE_COUNT & 0xFF;
     COUNT = 0;                                                                 //обнуляем счетчик байтов
     while (COUNT < RX_BYTE_COUNT)                                              //запускаем цикл сохранения байтов
           {
          *(DATA_IN_ADRESS + COUNT) = AT91C_BASE_UDP -> UDP_FDR[i];             //сохраняем инфу в память
           while (!((AT91C_BASE_US0 -> US_CSR) & AT91C_US_TXRDY));
           AT91C_BASE_US0  -> US_THR = *(DATA_IN_ADRESS + COUNT);
           COUNT++;                                                             //инкрементируем счетчик байтов
           }
     while (!((AT91C_BASE_US0 -> US_CSR) & AT91C_US_TXRDY));
     AT91C_BASE_US0  -> US_THR = 0xA3;
     }
//==============================================================================

    

//==============================================================================
//---Блок обработки прерываний от i-ой конечной точки---------------------------
void USB_EP_INT()
     {
//---Обработка управляющего пакета----------------------------------------------
     if ((AT91C_BASE_UDP -> UDP_CSR[i]) & AT91C_UDP_RXSETUP)                    //Если пришел управляющий пакет данных или команда
          {
          DATA_IN_ADRESS = (unsigned char *) &TSetupPacket;                     //присваиваем указателю адрес памяти где расположена структура управляющего пакета
          USB_RECEIVE_EP();                                                     //переход на функцию сохранения байтов в память
          while (1);
          switch (TSetupPacket.bRequest)                                        //че комп от меня хочет?
               {
               case GET_DESCRIPTOR:
                    {
                    while (!((AT91C_BASE_US0 -> US_CSR) & AT91C_US_TXRDY));
                    AT91C_BASE_US0  -> US_THR = 0xA4;
                    while (1);
                    DATA_OUT_ADRESS = (unsigned char *) &USB_DEVICE_DESCRIPTOR; //присваиваем указателю адрес памяти где расположена структура дескриптора устройства
                    TX_BYTE_COUNT   = *DATA_OUT_ADRESS;                         //присваиваем счетчику байтов длинну дескриптора устройства
                    AT91C_BASE_UDP -> UDP_CSR[i] |= AT91C_UDP_DIR;              //меняем направление передачи к хосту
                    AT91C_BASE_UDP -> UDP_CSR[i]  = !(AT91C_UDP_RXSETUP);       //Сброс бита RXSetup (данные из буфера прочитал)
                    USB_TRANSMIT_EP();                                          //Запись в буфер конечной точки дескриптора устройства
                    break;                                                      //выход из оператора switch
                    }
               case SET_ADRESS:
                    {
                    while(1);
                    }
               case GET_STATUS:
                    {
                    while(1);
                    }
               case CLEAR_FEATURE:
                    {
                    while(1);
                    }
               case SET_FEATURE:
                    {
                    while(1);
                    }
               case SET_DESCRIPTOR:
                    {
                    while(1);
                    }
               case GET_CONFIGURATION:
                    {
                    while(1);
                    }
               case SET_CONFIGURATION:
                    {
                    while(1);
                    }
               case GET_INTERFACE:
                    {
                    while(1);
                    }
               case SET_INTERFACE:
                    {
                    while(1);
                    }
               case SYNC_FRAME:
                    {
                    while(1);
                    }
               default:                                                         //если запрос не известен то выход из оператора switch
                    {
                    while(1);
                    }
               }
          //AT91C_BASE_UDP -> UDP_CSR[i]  = !(AT91C_UDP_RXSETUP);
          while(1);
          }

//---Обработка подтверждения приема пакета хстом--------------------------------
     if ((AT91C_BASE_UDP -> UDP_CSR[i]) & AT91C_UDP_TXCOMP)                     //Если пришел пакет подтверждения от хоста доставленых ему байтов
          {
          while(1);
          }

//------------------------------------------------------------------------------
     if ((AT91C_BASE_UDP -> UDP_CSR[i]) & AT91C_UDP_RX_DATA_BK0)                //Если есть данные в банке данных BK0
          {
          while(1);
          }
    
//------------------------------------------------------------------------------
     if ((AT91C_BASE_UDP -> UDP_CSR[i]) & AT91C_UDP_RX_DATA_BK1)                //Если есть данные в банке данных BK1
          {
          while(1);
          }

//------------------------------------------------------------------------------
     if ((AT91C_BASE_UDP -> UDP_CSR[i]) & AT91C_UDP_ISOERROR)                   //Хост принял останов или возникла ошибка CRC
          {
          while(1);
          }
    
//------------------------------------------------------------------------------
     }
//==============================================================================



//==============================================================================
//---Обработчик прерываний USB--------------------------------------------------
usb_main()
     {
//------------------------------------------------------------------------------
     switch ((AT91C_BASE_UDP -> UDP_ISR) & AT91C_UDP_ALL_EP_INT)                //выбор конечной точки, которая вызвала прерывание
          {
          case AT91C_UDP_EPINT0: {i = 0; USB_EP_INT(); break;}
          case AT91C_UDP_EPINT1: {i = 1; USB_EP_INT(); break;}
          case AT91C_UDP_EPINT2: {i = 2; USB_EP_INT(); break;}
          case AT91C_UDP_EPINT3: {i = 3; USB_EP_INT(); break;}
          case AT91C_UDP_EPINT4: {i = 4; USB_EP_INT(); break;}
          case AT91C_UDP_EPINT5: {i = 5; USB_EP_INT(); break;}
          }
//------------------------------------------------------------------------------
     if ((AT91C_BASE_UDP -> UDP_ISR) & AT91C_UDP_RXRSM)
          {
          while (!((AT91C_BASE_US0 -> US_CSR) & AT91C_US_TXRDY));
          AT91C_BASE_US0  -> US_THR = 0xF1;
          AT91C_BASE_UDP -> UDP_ICR = AT91C_UDP_RXRSM;
          }
     if ((AT91C_BASE_UDP -> UDP_ISR) & AT91C_UDP_RXSUSP)
          {
          while (!((AT91C_BASE_US0 -> US_CSR) & AT91C_US_TXRDY));
          AT91C_BASE_US0  -> US_THR = 0xF2;
          AT91C_BASE_UDP -> UDP_ICR = AT91C_UDP_RXSUSP;
          }
     if ((AT91C_BASE_UDP -> UDP_ISR) & AT91C_UDP_SOFINT)
          {
          while (!((AT91C_BASE_US0 -> US_CSR) & AT91C_US_TXRDY));
          AT91C_BASE_US0  -> US_THR = 0xF3;
          AT91C_BASE_UDP -> UDP_ICR = AT91C_UDP_SOFINT;
          }
     if ((AT91C_BASE_UDP -> UDP_ISR) & AT91C_UDP_ENDBUSRES)
          {
//---Конфигурация USB при сбросе шины-------------------------------------------
          AT91C_BASE_UDP  -> UDP_FADDR   =  AT91C_UDP_FEN;
          AT91C_BASE_UDP  -> UDP_RSTEP   =  AT91C_UDP_ALL_EP;                                  //Сброс всех конечных точек
          AT91C_BASE_UDP  -> UDP_ICR     =  AT91C_UDP_CLEAR_INT & (~AT91C_UDP_ENDBUSRES);      //Сброс прерываний кроме прерывания по сбросу шины
          AT91C_BASE_UDP  -> UDP_IDR     =  AT91C_UDP_ALL_INT;                                 //Запрещаем все прерывания
          AT91C_BASE_UDP  -> UDP_IER     =  AT91C_UDP_EPINT0;                                  //Разрешить прерывание от 0 конечной точки
          AT91C_BASE_UDP  -> UDP_CSR[AT91C_UDP_EP0] =  AT91C_UDP_EPTYPE_CTRL | AT91C_UDP_EPEDS;//0 конечная контрольная точка
          AT91C_BASE_UDP  -> UDP_ICR     = AT91C_UDP_ENDBUSRES;
          //while (!((AT91C_BASE_US0 -> US_CSR) & AT91C_US_TXRDY));
          //AT91C_BASE_US0  -> US_THR = 0xF4;
          }
     if ((AT91C_BASE_UDP -> UDP_ISR) & AT91C_UDP_WAKEUP)
          {
          while (!((AT91C_BASE_US0 -> US_CSR) & AT91C_US_TXRDY));
          AT91C_BASE_US0  -> US_THR = 0xF5;
          AT91C_BASE_UDP -> UDP_ICR = AT91C_UDP_WAKEUP;
          }
//------------------------------------------------------------------------------
     AT91C_BASE_AIC -> AIC_EOICR = 0xF1F1F1F1;                                  //Сообщаем AIC прерывание обработал :-)
     }
//==============================================================================


причина почему так много While(1), потому как код в стадии отладки)

хотя у меня есть такое предположение что приемопередатчик просто не успевает принять данные...
контроллер тактируется от PLL частота 48 МГц...
aaarrr
Цитата(shrek @ Feb 19 2009, 14:53) *
хотя у меня есть такое предположение что приемопередатчик просто не успевает принять данные...
контроллер тактируется от PLL частота 48 МГц...

Не успевать он не может по определению. Попробуйте поставить затычку, и просто сбрасывать RXSETUP, если длина 0. На каких-то хостах у меня такое встречалось, насколько я помню.
shrek
я сбрасывал бит RXSETUP если длинна равна 0. но он мне так и ничего не принял... все время равны 0...
aaarrr
Еще забыли FEN поставить:
Код
AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN;
shrek
так яж этот бит ставлю при сбросе шины
Код
if ((AT91C_BASE_UDP -> UDP_ISR) & AT91C_UDP_ENDBUSRES)
          {
//---Конфигурация USB при сбросе шины-------------------------------------------
          AT91C_BASE_UDP  -> UDP_FADDR   =  AT91C_UDP_FEN;
          AT91C_BASE_UDP  -> UDP_RSTEP   =  AT91C_UDP_ALL_EP;                                  //Сброс всех конечных точек
          AT91C_BASE_UDP  -> UDP_ICR     =  AT91C_UDP_CLEAR_INT & (~AT91C_UDP_ENDBUSRES);      //Сброс прерываний кроме прерывания по сбросу шины
          AT91C_BASE_UDP  -> UDP_IDR     =  AT91C_UDP_ALL_INT;                                 //Запрещаем все прерывания
          AT91C_BASE_UDP  -> UDP_IER     =  AT91C_UDP_EPINT0;                                  //Разрешить прерывание от 0 конечной точки
          AT91C_BASE_UDP  -> UDP_CSR[AT91C_UDP_EP0] =  AT91C_UDP_EPTYPE_CTRL | AT91C_UDP_EPEDS;//0 конечная контрольная точка
          AT91C_BASE_UDP  -> UDP_ICR     =  AT91C_UDP_ENDBUSRES;
          //while (!((AT91C_BASE_US0 -> US_CSR) & AT91C_US_TXRDY));
          //AT91C_BASE_US0  -> US_THR = 0xF4;
          }
aaarrr
Да, не заметил. Тогда проверьте, что у Вас i == 0.
Кстати, зачем использовать всюду глобальные переменные?
shrek
к вопросам по глобальности переменных я пока не подходил и всегда делал их глобальными...
i пока не проверял... думаю завтра....
sergeeff
На сайте Atmel'a появилась свежая версия библиотеки at91lib_softpack_1.5. Там есть модуль usb. Посмотри как там все реализовано.
shrek
В принципе я понял почему конфигурационный пакет не принимался
сброс прерываний при сбросе шины не нужно было делать
Код
AT91C_BASE_UDP  -> UDP_ICR     =  AT91C_UDP_CLEAR_INT & (~AT91C_UDP_ENDBUSRES);

эта строчка в коде просто не нужна была
после того как убрал эту строчку стал принимать пакет корректно)
sergeeff спасибо за инфу)
но все же если не разберешься на уровне приближенном к "машинному" и не выявишь все тонкости и проблемы... разобраться без этого будет сложновато почему девайс не работает)
shrek
теперь вопрос в другом... что должен содержать в себе дескриптор устройства?)

Конкретно параметры
Код
unsigned char bcdUSBL;              //версия спецификации USB в формате BCD
     unsigned char bcdUSBH;              //версия спецификации USB в формате BCD
     unsigned char bDeviceClass;         //код класса устройства USB
     unsigned char bDeviceSubclass;      //код подкласса устройства USB
     unsigned char bDeviceProtocol;      //код протокола USB
     unsigned char idVendorL;            //идентификатор изготовителя устройства
     unsigned char idVendorH;            //идентификатор изготовителя устройства
     unsigned char idProductL;           //идентификатор продукта
     unsigned char idProductH;           //идентификатор продукта
     unsigned char bcdDeviceL;           //номер версии устройства в формате BCD
     unsigned char bcdDeviceH;           //номер версии устройства в формате BCD
     unsigned char iManufacture;         //индекс дескриптора строки описывающей  изготовителя
     unsigned char iProduct;             //индекс дескриптора строки описывающей  продукт
     unsigned char iSerialNumber;        //индекс дескриптора строки описывающей  серийный номер устройства
     unsigned char bNumConfigurations;   //количество возможных конфигураций устройства



и еще я ему пытаюсь отослать дескриптор устройства 2 байта отослать удается
дальше хост сбрасывает шину и все снова...

по библиотекам (спасибо sergeeff) параметры
Код
     unsigned char bDeviceClass;         //код класса устройства USB
     unsigned char bDeviceSubclass;      //код подкласса устройства USB
     unsigned char bDeviceProtocol;      //код протокола USB

равны нулю

для HID устройств
(я пытаюсь для начала мышку реализовать)

судя по библиотекам первым младший байт отправлять не надо...

в общем я хосту пытаюсь отправить дескриптор устройства
Код
static const struct USB_DEVICE_DESCRIPTOR
     {
     unsigned char bLenth;               //0x12
     unsigned char bDescriptorType;      //0x01
     unsigned short int bcdUSBL;         //0x0200
     unsigned char bDeviceClass;         //0x00
     unsigned char bDeviceSubclass;      //0x00
     unsigned char bDeviceProtocol;      //0x00
     unsigned char bMaxPacketSize0;      //0x08
     unsigned short int idVendor;        //0x03EB
     unsigned short int idProduct;       //0x6200
     unsigned short int bcdDevice;       //0x0100
     unsigned char iManufacture;         //0x00
     unsigned char iProduct;             //0x00
     unsigned char iSerialNumber;        //0x00
     unsigned char bNumConfigurations;   //0x01

после того как девайс отправит 2ые 8 байт, то есть последнее что передает это bcdDevice, следует сброс шины и все начинается заново.
первые 8 байт девайс без проблем передает, далее следует подтверждение приема я передаю следующие 8 байт, далее следует сброс шины и все снова...???
amw
Цитата(shrek @ Feb 24 2009, 12:59) *
теперь вопрос в другом... что должен содержать в себе дескриптор устройства?)

Ниже выглядит правильно. Если с выравниеванием все в порядке, то вроде нормально.
Цитата
и еще я ему пытаюсь отослать дескриптор устройства 2 байта отослать удается
дальше хост сбрасывает шину и все снова...

Как два байта? Отсылать нужно по размеру конечной точки, или сколько есть если есть меньше чем размер конечной точки.
например есть дескриптор устройства 18 байт длиной. Тогда отсылается он в три приема: 8 + 8 + 2.
Как в AT91SAM7A3 я не знаю, а в SAM7S, если нужно отослать данные длиной, кратной размеру конечной точки, то после отрпавления последней порции и получения подтверждения нужно послать еще ноль байт.
Цитата
в общем я хосту пытаюсь отправить дескриптор устройства
Код
static const struct USB_DEVICE_DESCRIPTOR
     {
     unsigned char bLenth;               //0x12
     unsigned char bDescriptorType;      //0x01
     unsigned short int bcdUSBL;         //0x0200
     unsigned char bDeviceClass;         //0x00
     unsigned char bDeviceSubclass;      //0x00
     unsigned char bDeviceProtocol;      //0x00
     unsigned char bMaxPacketSize0;      //0x08
     unsigned short int idVendor;        //0x03EB
     unsigned short int idProduct;       //0x6200
     unsigned short int bcdDevice;       //0x0100
     unsigned char iManufacture;         //0x00
     unsigned char iProduct;             //0x00
     unsigned char iSerialNumber;        //0x00
     unsigned char bNumConfigurations;   //0x01

после того как девайс отправит 2ые 8 байт, то есть последнее что передает это bcdDevice, следует сброс шины и все начинается заново.
первые 8 байт девайс без проблем передает, далее следует подтверждение приема я передаю следующие 8 байт, далее следует сброс шины и все снова...???

Что-то математика не сходится. "после того как девайс отправит 2ые 8 байт, то есть последнее что передает это bcdDevice". 2 * 8 = 16, т.е. последним будет iProduct.
У Вас с выравниванием структуры все в порядке? Она должна быть упакованной.
shrek
Ссори правильно последний байт отсылает iProduct виноват)
Теперь что он отсылает (смотрю в отладке)
Запрос конфигурации 80 06 00 01 00 00 40 00
Посылка 1ых 8 байт дескриптора устройства 12 01 00 02 00 00 00 08
Хост подтверждает прием и посылает 2ые 8 байт EB 03 27 61 00 01 00 00
Дальше следует сброс шины и все заново
shrek
Форумчане...
В общем после нескольких "экспериментов"
все таки я не добился того почему после отправки 2х байтов дескриптора устройства следует сброс шины... но...
после сброса шины как ни странно следует пакет установки адреса...
принял запрос дескриптора 80 06 00 01 00 00 40 00
начинаю отсылать дескриптор устройства
1ые 8 байт 12 01 10 01 00 00 00 08
пришло подтверждение далее второй байт отсылаю
2ые 8 байт EB 03 00 62 00 01 00 00
далее приходит прерывание SOFINT и прерывание по наличию данных в банке 0
в банке данных 0 байт я сбросил бит подтвердил то что принял данные
далее следует сброс шины и приходит конфигурационный пакет 00 05 01 00 00 00 00 00
я так понимаю это установка адреса
глупый вопрос почему отправляется 16 байт а не 18?) это своеобразная особенность хоста?)

и еще 3 байт пакета 00 05 01 00 00 00 00 00 я так понимаю это адрес устройства который я должен записать?)
shrek
после установки адреса необходимо отослать нулевые данные?
aaarrr
Да, нужно.
shrek
перед установкой адреса или после?...
если после установки адреса
Код
case SET_ADRESS:
                    {
                    AT91C_BASE_UDP -> UDP_FADDR  |= TSetupPacket.ValueL & AT91C_UDP_FADD;//Присваиваем принятый адрес устройству
                    AT91C_BASE_UDP -> UDP_GLBSTATE = AT91C_UDP_FADDEN;          //Устанавливаем бит сигнализирующий что устройство в состоянии адреса
                    AT91C_BASE_UDP -> UDP_CSR[i] |= AT91C_UDP_DIR;              //меняем направление передачи к хосту
                    AT91C_BASE_UDP -> UDP_CSR[i] &= (~AT91C_UDP_RXSETUP & (~0x30));//Сброс бита RXSetup (данные из буфера прочитал)
                    while ((AT91C_BASE_UDP -> UDP_CSR[i]) & AT91C_UDP_TXPKTRDY);
                    AT91C_BASE_UDP -> UDP_CSR[i] |= AT91C_UDP_TXPKTRDY;
                    break;
                    }

то следует два раза прерывание SOFINT и опять сброс шины и по новой все
если перед установкой отправить нулевой пакет
Код
case SET_ADRESS:
                    {
                    AT91C_BASE_UDP -> UDP_CSR[i] |= AT91C_UDP_DIR;              //меняем направление передачи к хосту
                    AT91C_BASE_UDP -> UDP_CSR[i] &= (~AT91C_UDP_RXSETUP & (~0x30));//Сброс бита RXSetup (данные из буфера прочитал)
                    while ((AT91C_BASE_UDP -> UDP_CSR[i]) & AT91C_UDP_TXPKTRDY);
                    AT91C_BASE_UDP -> UDP_CSR[i] |= AT91C_UDP_TXPKTRDY;
                    while ((AT91C_BASE_UDP -> UDP_CSR[i]) & AT91C_UDP_TXPKTRDY);
                    AT91C_BASE_UDP -> UDP_FADDR  |= TSetupPacket.ValueL & AT91C_UDP_FADD;//Присваиваем принятый адрес устройству
                    AT91C_BASE_UDP -> UDP_GLBSTATE = AT91C_UDP_FADDEN;          //Устанавливаем бит сигнализирующий что устройство в состоянии адреса
                    break;
                    }

то приходит подтверждение приема хост ждет примерно секунды 2 и опять заново шлет запрос дескриптора устройства
по подробнее можно описать процедуру установки адреса?
в спецификации и в даташите к девайсу пишут что нулевой пакет данных необходимо отправлять до установки адреса
aaarrr
Нужно отправить ZLP, дождаться TXCOMP, и уже после этого устанавливать адрес.
shrek
после того как принял 00 05 01 00 00 00 00 00
я отправил данные нулевой длинны
наступило прерывание TXCOMP я его сбросил установил адрес 01
далее приходит запрос дескриптора несколько иной формы 80 06 00 01 00 00 12 00
первоначально девайс принял 80 06 00 01 00 00 40 00
повинуясь своей логике девайс начинает отправлять дескриптор устройства
1ые 8 байт отправляет следует подтверждение TXCOMP
2ые 8 байт отправляет... но подтверждения не приходит... 5 секунд молчания сброс шины и все по новой...
Это какая то особенность хоста?... %)

что в этой ситуации делать непонятно... хост ничего не присылает, ждет чего то... 2ые 8 байт отправляются... подтверждения никакого
shrek
В общем я понял суть моей проблемы...
при обработке подтверждения приема я забыл одну деталь... менять направление передачи данных контрольной точки...
Код
//---Обработка подтверждения приема пакета хостом-------------------------------
     if ((AT91C_BASE_UDP -> UDP_CSR[i]) & AT91C_UDP_TXCOMP)                         //Если пришел пакет подтверждения от хоста доставленых ему байтов
          {
          while (!((AT91C_BASE_US0 -> US_CSR) & AT91C_US_TXRDY));
          AT91C_BASE_US0 -> US_THR = 0xF7;
          AT91C_BASE_UDP -> UDP_CSR[i] &= (~AT91C_UDP_TXCOMP) & (~0x30);            //сбрасываем бит TXCOMP
          if (TX_BYTE_COUNT > 0)
               {
               AT91C_BASE_UDP -> UDP_CSR[i] |= AT91C_UDP_DIR;                       //меняем направление передачи к хосту
               USB_TRANSMIT_EP();                                                   //если оставшиеся байты не переданы то передаем
               }
          }

Из за отсутствия этой строчки
Код
AT91C_BASE_UDP -> UDP_CSR[i] |= AT91C_UDP_DIR;

ниче не работало в общем...
после этого весь дескриптор устройства отправляется хост его подверждает и присылает далее запрос конфигурации
80 06 00 02 00 00 09 00
))) надеюсь все написанное в этой теме поможет начинающим осваивать USB с нуля
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.