Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Код получения прерывания от RXSETUP на SAM7S
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
Shaienn
Добрый день. Посмотрите пожалуйста код. Ожидается, что при получении Control пакета возникнет бит RXSETUP и будет вызвано прерывание isrUDP, но в прерывание не заходит.

CODE
#include <AT91SAM7S256.H> /* AT91SAMT7S64 definitions */
#include <lib_AT91SAM7S256.h>
/*
* Main Program
*/
int i;
__irq void isrUDP(void)
{
unsigned int status = AT91C_BASE_UDP->UDP_ISR;
AT91PS_UDP pUDP = AT91C_BASE_UDP;
AT91_REG isr = pUDP->UDP_ISR;
AT91_REG csr = pUDP->UDP_CSR[0]; //rejestr csr endpointu 0
if (isr&AT91C_UDP_EPINT0)
{
if (i)
{
AT91C_BASE_PIOA->PIO_SODR = 1;
i = 0;
}
else
{
AT91C_BASE_PIOA->PIO_CODR = 1;
i = 1;
}
}
AT91C_BASE_UDP->UDP_CSR[0] = (0<<AT91C_UDP_RXSETUP);
AT91C_BASE_AIC->AIC_EOICR = status;
}

int main (void) {
AT91C_BASE_PIOA->PIO_PER = (1 << AT91C_PIO_PA0);
AT91C_BASE_PIOA->PIO_OER = 0x00000001;
AT91C_BASE_PMC->PMC_PCER = (1UL << AT91C_ID_PIOA);

// Set the PLL USB Divider
AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1;
AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP; //Разрешили частоту на UDP
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP);

AT91C_BASE_UDP->UDP_RSTEP = (1 << 0);
AT91C_BASE_UDP->UDP_RSTEP = 0;
AT91C_BASE_UDP->UDP_CSR[0] = AT91C_UDP_EPTYPE_CTRL;
AT91C_BASE_UDP->UDP_CSR[0] = AT91C_UDP_EPEDS;

// Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO
// Set in PIO mode and Configure in Output
AT91F_PIO_CfgOutput(AT91C_BASE_PIOA,AT91C_PIO_PA16);
// Clear for set the Pul up resistor
AT91F_PIO_ClearOutput(AT91C_BASE_PIOA,AT91C_PIO_PA16);

AT91C_BASE_UDP->UDP_IMR = AT91C_UDP_ENDBUSRES|AT91C_UDP_EPINT0;
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_UDP] = (unsigned int)isrUDP;
AT91C_BASE_AIC->AIC_SMR[AT91C_ID_UDP] = 6;
AT91C_BASE_AIC->AIC_IECR = (1UL << AT91C_ID_UDP);

// Loop forever
for (;;)
{
}
}


При чтении состояния регистра UDP_ISR в главном цикле без прерывания при данных настройках возвращает 0x00000100 (хотя должен 0x00000001). смотрю через дебаггер ulink. При замене AT91C_UDP_EPINT0 на AT91C_UDP_EPINT2 все равно не работает.

Вроде бы все указал... Затык.


Спасибо.
vmp
Почему бы не взять за основу какой-нибудь атмеловский пример по работе с USB?
Запустить его, посмотреть как он работает, а затем уже дорабатывать под свои нужды.
Там пока дойдет дело до RXSETUP, надо еще кучу событий обработать.
sergeeff
Глобальная переменная i первоначально не инициализирована. Это так, к сведению.
Shaienn
Цитата
Почему бы не взять за основу какой-нибудь атмеловский пример по работе с USB?
Запустить его, посмотреть как он работает, а затем уже дорабатывать под свои нужды.
Там пока дойдет дело до RXSETUP, надо еще кучу событий обработать.


Я бы рад, но как атмеловские проекты под IAR запустить в Keil`e? А через IAR не могу, ибо имею Ulink, который Keil only. Приходится разгребать самому.

Я так понимаю, что после подключения устройства к USB порту, хост отсылает Control пакет на который USB-устройство должно ответить. До ответа я еще не дошел, но хочу зафиксировать принятие этого пакета.
Намекните, какие еще события должны произойти до этого?

Цитата(sergeeff @ Nov 20 2009, 13:50) *
Глобальная переменная i первоначально не инициализирована. Это так, к сведению.

Согласно Источнику
Цитата
2. Глобальные переменные всегда инициализируются, и если это не сделано явно, то они инициализируются нулевым значением.


Или это не правда?
vmp
Цитата(Shaienn @ Nov 20 2009, 14:00) *
Я бы рад, но как атмеловские проекты под IAR запустить в Keil`e?

А зачем запускать в Кейле Иаровские примеры? Не проще ли сразу взять пример под Кейл:
Цитата
AT91SAM7S-EK Software Package for IAR 5.2, Keil and GNU (37 MB, updated 12/08)
This package provides software drivers and libraries to build any application for AT91SAM7S devices.

http://www.atmel.com/dyn/resources/prod_do...t91sam7s-ek.zip
aaarrr
Цитата(Shaienn @ Nov 20 2009, 11:02) *
Ожидается, что при получении Control пакета возникнет бит RXSETUP и будет вызвано прерывание isrUDP, но в прерывание не заходит.

Вообще-то задолго до RXSETUP случится ENDBUSRES, который этот самый RXSETUP успешно запретит.
Shaienn
2vmp
Спасибо за ссылку. Куча откровений smile.gif

Цитата(aaarrr @ Nov 23 2009, 10:04) *
Вообще-то задолго до RXSETUP случится ENDBUSRES, который этот самый RXSETUP успешно запретит.

Это уже стало понятно smile.gif


В процессе разбирания USB, понял следующее.

1) Подключаем подтяжку к D+, с этого момента хост считает, что устройство присоединено.
2) Хост производит процедуру сброса, после которой возникает флаг ENDBUSRES.

В связи с этим следующие вопросы:
1) Я так понимаю, что прерывание ENDBUSRES нигде в регистрах разрешения прерываний не объявляется и прерывание разрешено изначально?
2) Почему-то в моем Keil нет возможности при отладке заглянуть в регистры UDP и в AIC нет регистра прерывания UDP. Это лечится?
aaarrr
Цитата(Shaienn @ Nov 25 2009, 07:16) *
1) Я так понимаю, что прерывание ENDBUSRES нигде в регистрах разрешения прерываний не объявляется и прерывание разрешено изначально?

Да.

Цитата(Shaienn @ Nov 25 2009, 07:16) *
2) Почему-то в моем Keil нет возможности при отладке заглянуть в регистры UDP и в AIC нет регистра прерывания UDP. Это лечится?

Регистр прерывания UDP никакого отношения к AIC'у не имеет.
Shaienn
Цитата(aaarrr @ Nov 25 2009, 14:40) *
Регистр прерывания UDP никакого отношения к AIC'у не имеет.


Хм, а вот в этой штуке
Цитата
AT91SAM7S-EK Software Package for IAR 5.2, Keil and GNU (37 MB, updated 12/08)
This package provides software drivers and libraries to build any application for AT91SAM7S devices.

прерывание UDP делается через AIC:
Код
    AIC_ConfigureIT(AT91C_ID_UDP, 0, USBD_InterruptHandler);
    AIC_EnableIT(AT91C_ID_UDP);


А сами функции:
Код
void AIC_ConfigureIT(
    unsigned int source,
    unsigned int mode,
    void (*handler)(void))
{
    // Disable the interrupt first
    AT91C_BASE_AIC->AIC_IDCR = 1 << source;

    // Configure mode and handler
    AT91C_BASE_AIC->AIC_SMR[source] = mode;
    AT91C_BASE_AIC->AIC_SVR[source] = (unsigned int) handler;

    // Clear interrupt
    AT91C_BASE_AIC->AIC_ICCR = 1 << source;
}


Может я чего-то не понимаю?
aaarrr
Цитата(Shaienn @ Nov 25 2009, 15:33) *
Может я чего-то не понимаю?

В AIC заводится только сигнал прерывания UDP, точно так же, как и сигналы другой периферии. Какой "регистр прерывания UDP" вы хотите там увидеть?
Shaienn
Цитата(aaarrr @ Nov 25 2009, 18:12) *
В AIC заводится только сигнал прерывания UDP, точно так же, как и сигналы другой периферии. Какой "регистр прерывания UDP" вы хотите там увидеть?


Я неправильно выразился. Когда отлаживал прерывания разной периферии, Keil позволял посмотреть, все ли настройки установились и позволял увидеть вектор прерывания для данной периферии, но вот UDP в списке периферии Keil-а нет.
Shaienn
Здравствуйте.

Поправьте меня в процессе отправки дескриптора.

1) Возникает прерывание RXSETUP
2) Принимаем управляющую посылку 8 байт, читаем 2-й байт bRequest и 3-й байт слова wValue.
3) Первым возникает запрос GET_DESCRIPTOR типа "стандартный дескриптор устройства"
4) Начинаем отсылать первые 8 байт дескриптора
5) Ставим флаг TXPKTRDY
6) Ждем флага TXCOMP
7) Отсылаем вторые 8 байт дескриптора
8) Ставим флаг TXPKTRDY
9) Ждем флага TXCOMP
10) Отсылаем последние 2 байта
11) Ставим флаг TXPKTRDY
12) Ждем флага TXCOMP
13) Освобождаем конечную точку
14) Должно возникнуть следующее прерывание RXSETUP с запросом дескриптора конфигурации

Два вопроса:
1) Академический. При считывании управляющей посылки ее поле wLength не 18, а 64 байта. В Атмеловском примере они специально проверяют на это несовпадение и фиксируют его:
Код
if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice)) {

                length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice);
            }


Почему такая штука?

2) Практический. Вроде бы отправляю весь дескриптор устройства, но в следующем RXSETUP хост опять требует его же. Так происходит 3 раза, затем хост говорит, что USB устройство работает неправильно. Если хост требует дескриптор устройства снова и снова это значит, что я ему отправляю что-то неправильное? Вроде, все как завещано.
aaarrr
Цитата(Shaienn @ Nov 29 2009, 18:51) *
Почему такая штука?

Потому что по спецификации хост может запросить много. А отправить вы должны не более чем запрошено.

Цитата(Shaienn @ Nov 29 2009, 18:51) *
Если хост требует дескриптор устройства снова и снова это значит, что я ему отправляю что-то неправильное? Вроде, все как завещано.

Значит неправильно отправляете - не вовремя снимаете RXSETUP, не вовремя или неправильно ставите DIR и т.п.
Shaienn
Тогда посмотрите пожалуйста код:

CODE
/// Bitmap for all status bits in CSR.
#define REG_NO_EFFECT_1_ALL AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 \
|AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP \
|AT91C_UDP_TXCOMP

/// Clears the specified bit(s) in the UDP_CSR register.
/// \param endpoint The endpoint number of the CSR to process.
/// \param flags The bitmap to set to 1.
#define SET_CSR(endpoint, flags) \
{ \
volatile unsigned int reg; \
reg = AT91C_BASE_UDP->UDP_CSR[endpoint]; \
reg |= REG_NO_EFFECT_1_ALL; \
reg |= (flags); \
AT91C_BASE_UDP->UDP_CSR[endpoint] = reg; \
while ( (AT91C_BASE_UDP->UDP_CSR[endpoint] & (flags)) != (flags)); \
}

/// Sets the specified bit(s) in the UDP_CSR register.
/// \param endpoint The endpoint number of the CSR to process.
/// \param flags The bitmap to clear to 0.
#define CLEAR_CSR(endpoint, flags) \
{ \
volatile unsigned int reg; \
reg = AT91C_BASE_UDP->UDP_CSR[endpoint]; \
reg |= REG_NO_EFFECT_1_ALL; \
reg &= ~(flags); \
AT91C_BASE_UDP->UDP_CSR[endpoint] = reg; \
while ( (AT91C_BASE_UDP->UDP_CSR[endpoint] & (flags)) == (flags)); \
}

//------------------------------------------------------------------------------
/// Структура конечных точек
//------------------------------------------------------------------------------
typedef struct {
unsigned short size;
char *pData;
unsigned int remaining;
unsigned char state;
}sEndpoint;
sEndpoint Endpoint[4];


//------------------------------------------------------------------------------
/// Заполнение FIFO буфера конечной точки
//------------------------------------------------------------------------------
static void USB_WriteFIFO(unsigned char EndpointNum)
{
signed int size = Endpoint[EndpointNum].size;
if (Endpoint[EndpointNum].remaining < size)
{
size = Endpoint[EndpointNum].remaining;
}
Endpoint[EndpointNum].remaining -= size;
while (size > 0) {
AT91C_BASE_UDP->UDP_FDR[EndpointNum] = *(Endpoint[EndpointNum].pData);
Endpoint[EndpointNum].pData++;
size--;
}
}

//------------------------------------------------------------------------------
/// Подготовка данных
//------------------------------------------------------------------------------
static char USB_PrepareTransfer(unsigned char EndpointNum, const void *pData,unsigned int Length)
{ if (Endpoint[EndpointNum].state != UDP_ENDPOINT_IDLE) {
return 0;
}
Endpoint[EndpointNum].remaining = Length;
Endpoint[EndpointNum].pData = (void *)pData;
while((AT91C_BASE_UDP->UDP_CSR[EndpointNum]&AT91C_UDP_TXPKTRDY)==AT91C_UDP_TXPKTRDY);
Endpoint[EndpointNum].state = UDP_ENDPOINT_SENDING;
USB_WriteFIFO(EndpointNum);
SET_CSR(EndpointNum, AT91C_UDP_TXPKTRDY); // Enable interrupt on endpoint
AT91C_BASE_UDP->UDP_IER = 1 << EndpointNum;
return 1;
}
//------------------------------------------------------------------------------
/// Если прерывание isrUDP возникло от конечной точки
//------------------------------------------------------------------------------
static void UDP_EndpointHandler(unsigned char EndpointNum)
{ unsigned int status = AT91C_BASE_UDP->UDP_CSR[EndpointNum];
if ((status & AT91C_UDP_TXCOMP) != 0)
{ cnt++; //Так я понял, что TXCOMP возникает только один раз
if (cnt == 2)
{
LED_Toggle(2);
}
if (Endpoint[EndpointNum].state == UDP_ENDPOINT_SENDING)
{
if (Endpoint[EndpointNum].remaining != 0) //Не все данные переданы
{
USB_WriteFIFO(EndpointNum);
SET_CSR(EndpointNum, AT91C_UDP_TXPKTRDY); //После этой строки больше TXCOMP не приходит
CLEAR_CSR(EndpointNum, AT91C_UDP_TXCOMP);
}
else
{
Endpoint[EndpointNum].state = UDP_ENDPOINT_IDLE;
CLEAR_CSR(EndpointNum, AT91C_UDP_TXCOMP);
}
}
else
{
CLEAR_CSR(EndpointNum, AT91C_UDP_TXCOMP);
}
}
if ((status & AT91C_UDP_RXSETUP) != 0)
{
if (count!=0){return;}
count++;
UDP_ReadRequest(&request);
if ((request.bmRequestType & 0x80) != 0)
{
SET_CSR(EndpointNum, AT91C_UDP_DIR); //меняем направление передачи данных
}
CLEAR_CSR(EndpointNum, AT91C_UDP_RXSETUP);
UDP_RequestReceived(&request);
}
}

//------------------------------------------------------------------------------
/// Обработчик прерывания AT91C_BASE_UDP
//------------------------------------------------------------------------------
__irq void isrUDP(void)
{
unsigned int status;
status = AT91C_BASE_UDP->UDP_ISR;
status &= AT91C_BASE_UDP->UDP_IMR;
//Если прерывание по концу сброса шины:
if ((status & AT91C_UDP_ENDBUSRES) != 0)
{
// Enables the UDP transceiver.
AT91C_BASE_UDP->UDP_TXVC = (1 << AT91C_UDP_TXVDIS);
// Configure Endpoint 0 for CONTROL Transaction
ConfigureEndpoint(0);
//Reset ENDBUSRES interrupt
AT91C_BASE_UDP->UDP_ICR |= (unsigned int) 0x1 << 12;
}
//Если прерывание по восстановлению активности на шине:
else if ((status & (AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM)) != 0)
{
AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM;
AT91C_BASE_UDP->UDP_IDR = AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM;
}
//Если прерывание от конечной точки:
else if ((status & AT91C_UDP_EPINT0) != 0)
{
UDP_EndpointHandler(0);
}
//Прерывание выполнено
AT91C_BASE_AIC->AIC_EOICR = status;
}


Как я понял, происходит следующее. Прерывание RXSETUP обрабатывается, считываем пакет, расшифровываем его. Подготавливаем данные функцией USB_PrepareTransfer, из нее вызывается функция USB_WriteFIFO, где непосредственно записываем 8 байт в FIFO буфер. Затем возникает прерывание TXCOMP, которое обрабатывается в UDP_EndpointHandler, вызывается еще один раз функция USB_WriteFIFO без вызова USB_PrepareTransfer, передается еще 8 байт информации (Остается передать еще два) и после этого прерывание по TXCOMP больше не срабатывает.

То есть после USB_PrepareTransfer появляется TXCOMP, а после обработки этого TXCOMPа следующий TXCOMP уже не появляется. Что-то я уже голову сломал...

Функции SET_CSR и CLEAR_CSR взял из атмеловского примера:

CODE
/// Bitmap for all status bits in CSR.
#define REG_NO_EFFECT_1_ALL AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 \
|AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP \
|AT91C_UDP_TXCOMP

/// Clears the specified bit(s) in the UDP_CSR register.
/// \param endpoint The endpoint number of the CSR to process.
/// \param flags The bitmap to set to 1.
#define SET_CSR(endpoint, flags) \
{ \
volatile unsigned int reg; \
reg = AT91C_BASE_UDP->UDP_CSR[endpoint]; \
reg |= REG_NO_EFFECT_1_ALL; \
reg |= (flags); \
AT91C_BASE_UDP->UDP_CSR[endpoint] = reg; \
while ( (AT91C_BASE_UDP->UDP_CSR[endpoint] & (flags)) != (flags)); \
}

/// Sets the specified bit(s) in the UDP_CSR register.
/// \param endpoint The endpoint number of the CSR to process.
/// \param flags The bitmap to clear to 0.
#define CLEAR_CSR(endpoint, flags) \
{ \
volatile unsigned int reg; \
reg = AT91C_BASE_UDP->UDP_CSR[endpoint]; \
reg |= REG_NO_EFFECT_1_ALL; \
reg &= ~(flags); \
AT91C_BASE_UDP->UDP_CSR[endpoint] = reg; \
while ( (AT91C_BASE_UDP->UDP_CSR[endpoint] & (flags)) == (flags)); \
}

//------------------------------------------------------------------------------
/// Структура конечных точек
//------------------------------------------------------------------------------
typedef struct {
unsigned short size;
char *pData;
unsigned int remaining;
unsigned char state;
}sEndpoint;
sEndpoint Endpoint[4];


Модератор (rezident). Shaienn, предупреждаю Вас один раз. Либо Вы прикрепляете к сообщению исходники в виде файлов, как этого требуют Правила форума. Либо пользуйтесь тэгами [ codebox ] для оформления объемных цитат исходников, самостоятельно редактируя их так, чтобы страницу не "распирало". Я Вам не нянька, чтобы редактировать за Вас оформление Ваших же исходников! twak.gif
aaarrr
Код, я бы сказал, малость раздутый. Поле size действительно равно восьми? Есть явная ошибка, которая проявится, если размер передаваемых данных будет кратен размеру endpoint'а - в этом случае в конце не будет передан пакет нулевой длины.
И зачем вот это:
Код
                        if (count!=0){return;}        
                        count++;


И аккуратнее с атмеловскими примерами, макросы SET_CSR и CLEAR_CSR - это просто безобразие.
Shaienn
Вот функция конфигурирования конечной точки. Для нулевой точки пишу size = 8.

CODE
//------------------------------------------------------------------------------
/// Конфигурирование конечной точки
//------------------------------------------------------------------------------
static void ConfigureEndpoint(const int EndpointNum)
{
unsigned char Type;
unsigned char EndpointDir;
if (EndpointNum == 0)
{
Endpoint[EndpointNum].size=8;
Type= 0;
EndpointDir = 0;
}
else
{
//Other Endpoints
}

//Настройка регистра UDP_ CSRx [x = EndpointNumber]
SET_CSR(EndpointNum, (unsigned int)AT91C_UDP_EPEDS | (Type << 8) | (EndpointDir << 10));
Endpoint[EndpointNum].state = UDP_ENDPOINT_IDLE;
if (Type == 0) //Если точка контрольная, то разрешить прерывание EPxINT [x = EndpointNumber]
{
AT91C_BASE_UDP->UDP_IER = (1 << EndpointNum);
}
}


Макросы действительно большие, но атмеловский код работает, а мой нет. Вот и пытаюсь приближать. Как только получится результат, я перепишу весь код заново попроще smile.gif

А это:
Код
if (count!=0){return;}        
                        count++;


Для того, чтобы прошел только один RXSETUP... smile.gif
aaarrr
Цитата(Shaienn @ Nov 30 2009, 15:10) *
Для того, чтобы прошел только один RXSETUP... smile.gif

Уберите, зачем самоломающийся код нужен?
Shaienn
Уважаемый aaarrr, изучил тему с Вашим участием. Посмотрел пример Protossa. Сравнил со своим. Ну все так же. Но так и не отправляет последние два байта дескриптора, хотя почему-то происходит запрос SET_ADDRESS.

Не могли бы Вы заглянуть в мой проект, может и я банально затупил где-нибудь. Знаю, что тратите свое время. Буду очень благодарен.

Нажмите для просмотра прикрепленного файла
aaarrr
Цитата(Shaienn @ Dec 1 2009, 15:37) *
Но так и не отправляет последние два байта дескриптора, хотя почему-то происходит запрос SET_ADDRESS.

Да не нужны хосту ваши последние два байта (точнее, ему вообще нужны только первые 8) - он адрес установить хочет поскорее! Полностью дескриптор будет запрошен после.
Так что добавьте обработку запроса SET_ADDRESS, и все будет в порядке.
Shaienn
Ага спасибо. Процесс дошел до получения дескриптора конфигурации. В нем есть поле wTotalLength - общий объем данных (в байтах) возвращаемый для данной конфигурации.

Это поле равно:
Код
sizeof(USBConfigurationDescriptor)+sizeof(USBInterfaceDescriptor)


Или нет?
aaarrr
Цитата(Shaienn @ Dec 1 2009, 17:14) *
Или нет?

Нет, еще как минимум сумма длин дескрипторов endpoint'ов.
Shaienn
2aaarrr
Ок. Устройство распознается windows как неизвестное.

Немного не понимаю процесс конфигурирования. После запроса GET_CONFIGURATION отправляется дескриптор конфигурации в котором есть общая длина данных для передачи, включая, как Вы и сказали, длину дескриптора конфигурации, дескриптора интерфейса и двух точек. Также а дескрипторе конфигурации говорится, что данная конфигурация имеет один интерфейс. После отправки дескриптора конфигурации мне нужно ждать GET_INTERFACE_DESCRIPTOR? Или уже начинается работа драйвера для моего устройства? И в какой момент времени должен отправляться дескриптор первой точки, а когда второй.

smile.gif Спасибо за Вашу помощь.
aaarrr
На запрос конфигурации Вы должны отправить все сразу - дескриптор конфигурации, дескрипторы интерфейсов и конечных точек. После этого получите SET_CONFIGURATION, и начиная с этого момента сможете работать с устройством через свой драйвер.
Shaienn
А SET_CONFIGURATION приходит после того, как я установил драйвер в windows или вне зависимости от него?
aaarrr
После.
Shaienn
Добрый день.
Продолжаю свою эпопею.

Собрал в DriverStudio драйвер под свой девайс. Драйвер ставится, но выдает код 10 (невозможно запустить устройство). В микроконтроллере приходит SET_CONFIGURATION с номером конфигурации 0.
Видимо дело в драйвере.

У отсылаю такой общий дескриптор:
CODE

const DriverConfigurationDescriptors driverConfigurationDescriptor =
{
{
sizeof(USBConfigurationDescriptor),
USBGenericDescriptor_CONFIGURATION,
sizeof(DriverConfigurationDescriptors),
0, // No interface in this configuration
1, // This is configuration #1
0, // No string descriptor for this configuration
0,
USBConfigurationDescriptor_POWER(100)
},
{
sizeof(USBInterfaceDescriptor),
USBGenericDescriptor_INTERFACE,
0, // This is interface #0
0, // This is setting #0 for interface
2, // Interface has 2 endpoint
0, // No interface class code
0, // No interface subclass code
0, // No interface protocol code
0, // No string descriptor
},
{
sizeof(USBEndpointDescriptor),
USBGenericDescriptor_ENDPOINT,
(((0 & 0x01) << 7) | (1 & 0xF)),
2,
0x01,
0x00 // Does not apply to Bulk endpoints
},
// Bulk-IN endpoint descriptor
{
sizeof(USBEndpointDescriptor),
USBGenericDescriptor_ENDPOINT,
(((1 & 0x01) << 7) | (2 & 0xF)),
2,
0x01,
0x00 // Does not apply to Bulk endpoints
}

} ;


То есть хочу две точки, на вход и на выход.

Точки настроил так:
CODE

//------------------------------------------------------------------------------
/// Конфигурирование конечной точки
//------------------------------------------------------------------------------
static void ConfigureEndpoint0(void)
{
const int EndpointNum = 0;
AT91C_BASE_UDP->UDP_RSTEP = AT91C_UDP_EP0;
AT91C_BASE_UDP->UDP_RSTEP = 0;
Endpoint[EndpointNum].size=8;
SET_CSR(0,(unsigned int)AT91C_UDP_EPEDS | (0 << 8) | (0 << 7));
AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN;
AT91C_BASE_UDP->UDP_IER = (1 << EndpointNum);
}

//------------------------------------------------------------------------------
/// Конфигурирование конечной точки
//------------------------------------------------------------------------------
static void ConfigureEndpoint1(void)
{
const int EndpointNum = 1;
AT91C_BASE_UDP->UDP_RSTEP = AT91C_UDP_EP1;
AT91C_BASE_UDP->UDP_RSTEP = 0;
Endpoint[EndpointNum].size=64;
SET_CSR(1,(unsigned int)AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT | (1<<7));
AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN;
}

//------------------------------------------------------------------------------
/// Конфигурирование конечной точки
//------------------------------------------------------------------------------
static void ConfigureEndpoint2(void)
{
const int EndpointNum = 2;
AT91C_BASE_UDP->UDP_RSTEP = AT91C_UDP_EP2;
AT91C_BASE_UDP->UDP_RSTEP = 0;
Endpoint[EndpointNum].size=64;
SET_CSR(1,(unsigned int)AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN | (0<<7));
AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN;
}


Из за чего вообще такое может происходить? Укажите направление раскопок smile.gif



PS Раскопал. В конфигурационном дескрипторе сказал, что для данной конфигурации нет интерфейса.... smile.gif
Shaienn
Добрый день. После небольшой паузы возвращаюсь к этой задаче.
Используя WinDriver собрал драйвер для устройства и сейчас пытаюсь отправить что-то с микроконтроллера в windows.

написал следующую функцию:
Код
unsigned char Send64BytePacket(unsigned char EndpointNum, const void *pData)
{
unsigned int Length;
//Подготовка данных
if((AT91C_BASE_UDP->UDP_CSR[EndpointNum] & AT91C_UDP_TXPKTRDY)==0)
{
Length = sizeof(pData);
if (Length%Endpoint[EndpointNum].size == 0)
            {
            Endpoint[EndpointNum].options = SEND_ZERO_LENGTH_PKT;
            }
Endpoint[EndpointNum].remaining = Length;
Endpoint[EndpointNum].pData = (void *)pData;
//Процесс передачи
while(Endpoint[EndpointNum].remaining!=0)
{
unsigned int status = AT91C_BASE_UDP->UDP_CSR[EndpointNum];    

        if ((status & AT91C_UDP_TXPKTRDY) == 0)
        {
                            if (Endpoint[EndpointNum].remaining != 0) //Не все данные переданы
                                {
                                USB_WriteFIFO(EndpointNum);
                                CLEAR_CSR(EndpointNum,AT91C_UDP_TXCOMP);
                                }
                            else
                                {
                                if (Endpoint[EndpointNum].options == SEND_ZERO_LENGTH_PKT)
                                                    {
                                                    LED_Toggle(0);
                                                    USB_PrepareTransfer(EndpointNum,0,0);
                                                    Endpoint[EndpointNum].options =0;
                                                    }
                                CLEAR_CSR(EndpointNum,AT91C_UDP_TXCOMP);
                                }
        }

}
}
return 1;
}



В сниффере WinDriver`a ничего не вижу, в связи с этим пара вопросов:

а) В результате начальных действий устройство стоит в сконфигурированном состоянии.
Чтобы мне начать пересылку, мне нужно записать данные в FIFO и выставить флаг TXPKTRDY? Т.е. микроконтроллер начинает пересылку с момента появление флага TXPKTRDY в соответствующем UDP_CSR?

б) Посмотрите пожалуйста на дескриптор конечной точки на передачу к хосту:
Код
                      {
        sizeof(USBEndpointDescriptor),
        USBGenericDescriptor_ENDPOINT,
        (((0 & 0x01) << 7) | (2 & 0xF)),
        2,
        0x40,
        0x00                               // Does not apply to Bulk endpoints
                       }


и на инициализацию этой конечной точки:
Код
static void ConfigureEndpoint1(void)
{
const int EndpointNum = 1;
AT91C_BASE_UDP->UDP_RSTEP = AT91C_UDP_EP1;
AT91C_BASE_UDP->UDP_RSTEP = 0;
Endpoint[EndpointNum].size=64;
SET_CSR(1,(unsigned int)AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT);
AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN;
}


Не напортачил ли я где?

Заранее спасибо smile.gif
aaarrr
Цитата(Shaienn @ Jan 9 2010, 18:37) *
а) В результате начальных действий устройство стоит в сконфигурированном состоянии.
Чтобы мне начать пересылку, мне нужно записать данные в FIFO и выставить флаг TXPKTRDY? Т.е. микроконтроллер начинает пересылку с момента появление флага TXPKTRDY в соответствующем UDP_CSR?

Да.

Цитата(Shaienn @ Jan 9 2010, 18:37) *
б) Посмотрите пожалуйста на дескриптор конечной точки на передачу к хосту:

Это дескриптор OUT-точки, т.е. от хоста к устройству.

Цитата(Shaienn @ Jan 9 2010, 18:37) *
и на инициализацию этой конечной точки:

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

Цитата(Shaienn @ Jan 9 2010, 18:37) *
Не напортачил ли я где?

Вот, например:
Код
Length = sizeof(pData);

Length будет всегда равна 4-м.
Shaienn
Добрый день.

Написал такой тестовый код:
Код
unsigned char Send64BytePacket(unsigned char EndpointNum, const void *pData)
{
char code,*data;
signed int d;
signed int size;
d = 0x1f044a;
size = sizeof(d);
data = (void *)&d;
while(AT91C_BASE_UDP->UDP_CSR[EndpointNum]&AT91C_UDP_TXPKTRDY);
while (size--)
{
AT91C_BASE_UDP->UDP_FDR[EndpointNum] = *data;
data++;    
}
SET_CSR(EndpointNum,AT91C_UDP_TXPKTRDY);

return 1;


Почему я передаю 0x001f044a, а принимаю зеркальное 0x4a041f00? Это особенность USB или мой косяк?

Спасибо.
aaarrr
Цитата(Shaienn @ Jan 11 2010, 07:23) *
Почему я передаю 0x001f044a, а принимаю зеркальное 0x4a041f00? Это особенность USB или мой косяк?

Потому что SAM7 работает в режиме Little Endian. USB тут ни при чем никаким боком.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.