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

 
 
> USB и sam7s. Нужен простой проект с использованием прерываний, Почти написал свой но энумерация проходит не стабильно
mempfis_
сообщение Apr 6 2010, 20:07
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Всем добрый вечер.
На основе проекта usb-device-hid-transfer-project из примеров IAR 5.4 и собственных знаний по USB пишу своё HID-устройство.
В цело половина этапа энумерации уже преодолена (реализована передача общих запросов, осталась передача запроса класса устройства).
Но даже эта половина запросов работает нестабильно.
В процессе энумерации host может 3 раза запросить device descriptor а потом перевести устройство в suspend (хотя я вижу что я отправил этот дескриптор). Или какой-либо другой дескриптор (но чаще именно на device descriptor). Или после запроса device descriptor наступает bus reset.
Также бывает что все запросы (те которые уже реализованы) проходят гладко и у меня даже появляется неопознанное hid-устройство.
Подозреваю что это косяки моей программы (пример из IAR вроде работает хотя и ужасно запутан) - возможно в реализации обработки прерываний от UDP.

Интересует ссылка на какой-либо работающий (и не такой запутанный как иаровский) проект (под любой компилятор) с ипользованием USB в sam7s но обязательно с прерываниями.
Хочу сравнить реализацию обработчика прерываний и найти "10 отличий".

По-поводу своего проекта - помимо прерываний UDP используется PIT (раз в 1мС), USART0 (115200, в процессе энумерации через него выводятся различные сообщения), PIO (тоже по прерываниям но они практически не задействованы). Startup-код уверяет что возможны вложенные прерывания.

Не может-ли большое кол-во источников прерываний и возможность вложенных прерываний влиять на процесс энумерации? Ведь некоторые этапы энумерации ограничены во времени а вложенные прерывания задерживаю работу обработчика прерываний UDP или чтото в этом духе.

Вобщем буду благодарен всем кто даст ссылки на проекты или что-либо посоветут по организации работы UDP.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
aaarrr
сообщение Apr 6 2010, 20:34
Сообщение #2


Гуру
******

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



Цитата(mempfis_ @ Apr 7 2010, 00:22) *
Интересует ссылка на какой-либо работающий (и не такой запутанный как иаровский) проект (под любой компилятор) с ипользованием USB в sam7s но обязательно с прерываниями.
Хочу сравнить реализацию обработчика прерываний и найти "10 отличий".

Хорошо, а без прерываний ваш код работает?

Цитата(mempfis_ @ Apr 7 2010, 00:22) *
Не может-ли большое кол-во источников прерываний и возможность вложенных прерываний влиять на процесс энумерации? Ведь некоторые этапы энумерации ограничены во времени а вложенные прерывания задерживаю работу обработчика прерываний UDP или чтото в этом духе.

Ограничения 50-500мс. Не успеть нужно еще постараться.

Косяк скорее не в прерывании, а в каком-нибудь косяке типа установки DIR после сброса RXSETUP или TXPKTRDY после сброса TXCOMP.
Go to the top of the page
 
+Quote Post
mempfis_
сообщение Apr 7 2010, 07:42
Сообщение #3


Профессионал
*****

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Цитата
Хорошо, а без прерываний ваш код работает?

Без прерываний не пробовал. Писал сразу с использованием прерываний UDP.


Цитата
Косяк скорее не в прерывании, а в каком-нибудь косяке типа установки DIR после сброса RXSETUP или TXPKTRDY после сброса TXCOMP


Вот мой обработчик прерываний от Endpoint 0.
DIR у меня устанавливается один раз после приёма SETUP-пакета перед подтверждением прерывания.
TXPKTRDY перед подтверждением TXCOMP.

CODE
/*******************************************************************/
//обработчик прерывания от EP0
void ep0Handler(void)
{
unsigned int status = AT91C_BASE_UDP->UDP_CSR[0];

//PutString0("EP0 handler\r\n");

//in-трансакция - устройство шлёт данные на хост
if ((status & AT91C_UDP_TXCOMP) != 0)
{
PutString0("TXCOMP\r\n");

// EP0 в состоянии передачи?
if (epsCTRL[0].status == UDP_ENDPOINT_SENDING)
{
// проверяем завершение передачи
if(epsCTRL[0].tx_flag == 0)
{
epsCTRL[0].tx_flag = EP0_WritePayload(); //записываем следующий блок данных с проверкой статуса

AT91C_BASE_UDP->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY; //устанавливаем флаг начала передачи
AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_TXCOMP; //подтверждаем прерывание

}
else
{
//передача завершена
//переводим конечную точку в исходное состояние
epsCTRL[0].status = UDP_ENDPOINT_IDLE;
epsCTRL[0].pData = 0;
epsCTRL[0].totalLen = 0;
epsCTRL[0].sendLen = 0;
epsCTRL[0].tx_flag = 0;

//присваиваем устройству назначенный адрес
if(setAddr.flag)
{
setAddr.flag = 0;
SetAddress(setAddr.address); //устанавливаем назначенный адрес
}

PutString0("TX complet\r\n");
AT91C_BASE_UDP->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP); //подтверждаем прерывание

}
}
else
{
// подтверждаем прерывание
PutString0("Error Wr\r\n");
AT91C_BASE_UDP->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP); //подтверждаем прерывание
}
}


// OUT packet received
if ((status & (AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1)) != 0)
{
PutString0("UDP_RXDATA\r\n");

AT91C_BASE_UDP->UDP_CSR[0] &= ~(AT91C_UDP_RX_DATA_BK0|AT91C_UDP_RX_DATA_BK1);
}

// STALL sent
if ((status & AT91C_UDP_STALLSENT) != 0)
{
PutString0("STALLSENT\r\n");
AT91C_BASE_UDP->UDP_CSR[0] &= ~(AT91C_UDP_STALLSENT);

// If the endpoint is not halted, clear the STALL condition
if (epsCTRL[0].status != UDP_ENDPOINT_HALTED)
{
AT91C_BASE_UDP->UDP_CSR[0] &= ~(AT91C_UDP_FORCESTALL);
}
}

// принят setup-пакет
if ((status & AT91C_UDP_RXSETUP) != 0)
{

PutString0("RXSETUP:\r\n");

USBGenericRequest request; //структура хранения текущего запроса

//считываем setup-пакет
ep0ReadRequest(&request);

//определяем направление перед подтверждением приёма setup-пакета
if (GetDirection(&request) == USBGenericRequest_IN)
{
AT91C_BASE_UDP->UDP_CSR[0] |= AT91C_UDP_DIR;
}

//подтверждаем приём setup-пакета
AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_RXSETUP;

//передаём принятый пакет на обработку
ep0RequestHandler(&request);
}

}
/*************************************************/


Сама передача данных начинается таким образом:

Код
//------------------------------------------------------------------------------
//пересылка данных через EP0
//передаём указатель на данные и кол-во байт для передачи
char EP0_Write( const char *pData, unsigned int dLength)
{
  //PutString0("EP0 send data\r\n");

  //сохраняем указатель на данные, кол-во байт для пересылки
  //и обнуляем счётчик переданных байт
  epsCTRL[0].status = UDP_ENDPOINT_SENDING;
  epsCTRL[0].pData = pData;
  epsCTRL[0].totalLen = dLength; //всего байт на передачу
  epsCTRL[0].sendLen = 0; //всего послано байт
  epsCTRL[0].tx_flag = 0; //флаг того что передача завершена

  //ожидаем готовности к передаче
  while((AT91C_BASE_UDP->UDP_CSR[0]&AT91C_UDP_TXPKTRDY)==AT91C_UDP_TXPKTRDY);
  epsCTRL[0].tx_flag = EP0_WritePayload(); //записываем блок данных
  AT91C_BASE_UDP->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY; //инициируем передачу

  // разрешаем прерывание от конечной точки
  //для EP0 оно разрешено всегда
  AT91C_BASE_UDP->UDP_IER = 1 << 0;

  return 1;
}


В процессе эксперементов обнаружил интересное явление.

Вот моя функция загрузки данных в фифо конечной точки.

CODE
/****************************************/
//запись блока данных в EP0
unsigned char EP0_WritePayload(void)
{
int int_path, fract_path;

//вычисляем целую часть от того сколько осталось послать
int_path = (epsCTRL[0].totalLen - epsCTRL[0].sendLen)/EP0_SIZE;

//AT91C_BASE_UDP->UDP_CSR[0] |= AT91C_UDP_DIR;

if(int_path > 0)
{
//есть больше чем EP0_SIZE

for(unsigned char i=0; i<EP0_SIZE; i++)
{
AT91C_BASE_UDP->UDP_FDR[0] = *(epsCTRL[0].pData + epsCTRL[0].sendLen + i);
}

epsCTRL[0].sendLen += EP0_SIZE; //увеличиваем кол-во переданных байт на 8

AT91C_BASE_UDP->UDP_CSR[0] |= AT91C_UDP_DIR;

return 0; //признак - ещё не все данные переданы
}
else
{
//осталась часть пакета, если она больше 0 то дописываем байты и выдаём признак что это последняя передача
//иначе просто выдаём признак последняя передача чтобы послать пустой пакет

fract_path = (epsCTRL[0].totalLen - epsCTRL[0].sendLen)%EP0_SIZE; //вычисляем дробную часть от того сколько осталось послать
if(fract_path > 0)
{
//дописываем остаток пакета

for(unsigned char i=0; i<fract_path; i++)
{
AT91C_BASE_UDP->UDP_FDR[0] = *(epsCTRL[0].pData + epsCTRL[0].sendLen + i);
}


epsCTRL[0].sendLen += fract_path; //увеличиваем кол-во переданных байт на дробную часть

AT91C_BASE_UDP->UDP_CSR[0] |= AT91C_UDP_DIR;

}

return 1; //возвращаем признак что все данные переданы

}


}


В ней я принудительно устанавил флаг AT91C_BASE_UDP->UDP_CSR[0] |= AT91C_UDP_DIR после загрузки данных.
Так вот если я устанавливаю этот флаг так как сейчас в функции (по веткам условия int_path > 0 и fract_path > 0 т.е. реально чтото записываю в фифо) то получаю такой лог запросов:

CODE
CONNECT PULLUP
Start of programm
WAKEUP or RXRSM
WAKEUP or RXRSM
ENDBUSRES
RXSUSP
WAKEUP or RXRSM
ENDBUSRES

RXSETUP:
80 06 00 01 00 00 40 00
EP0: new request - standart Get Descriptor Device
UDP_RXDATA
ENDBUSRES

RXSETUP:
00 05 01 00 00 00 00 00
EP0: new request - standart Set AddressTX complet

RXSETUP:
80 06 00 01 00 00 12 00
EP0: new request - standart Get Descriptor Device
TX complet
UDP_RXDATA

RXSETUP:
80 06 00 02 00 00 09 00
EP0: new request - standart Get Descriptor Configuration
TX complet
UDP_RXDATA

RXSETUP:
80 06 00 03 00 00 FF 00
EP0: new request - standart Get Descriptor String
TX complet
UDP_RXDATA

RXSETUP:
80 06 03 03 09 04 FF 00
EP0: new request - standart Get Descriptor String
TX complet
UDP_RXDATA

RXSETUP:
80 06 00 02 00 00 FF 00
tring
TX complet
UDP_RXDATA

RXSETUP:
80 06 00 01 00 00 12 00
EP0: new request - standart Get Descriptor Device
TX complet
UDP_RXDATA

RXSETUP:
80 06 00 02 00 00 09 00
EP0: new request - standart Get Descriptor Configuration
TX complet
UDP_RXDATA

RXSETUP:
80 06 00 02 00 00 29 00
EP0: new request - standart Get Descriptor Configuration
TX complet
UDP_RXDATA

RXSETUP:
00 09 01 00 00 00 00 00
EP0: new request - standart Set ConfigurationTX complet

RXSETUP:
21 0A 00 00 00 00 00 00
EP0: new request - unsupported
STALLSENT

RXSETUP:
81 06 00 22 00 00 60 00
EP0: new request - standart unsupported
STALLSENT

RXSETUP:
81 06 00 22 00 00 60 00
EP0: new request - standart unsupported
STALLSENT

RXSETUP:
81 06 00 22 00 00 60 00
EP0: new request - standart unsupported
STALLSENT
RXSUSP


Если же я устанавливаю флаг AT91C_BASE_UDP->UDP_CSR[0] |= AT91C_UDP_DIR; перед каждым return
( для ветки int_path > 0 запись всегда осуществляется, а вот дробная часть пакета реально записывыается только если fract_path > 0 иначе формируется пакет нулевой длины ) то лог сокращается:

CODE
CONNECT PULLUP
Start of programm
WAKEUP or RXRSM
WAKEUP or RXRSM
ENDBUSRES
RXSUSP
WAKEUP or RXRSM
ENDBUSRES

RXSETUP:
80 06 00 01 00 00 40 00
EP0: new request - standart Get Descriptor Device
UDP_RXDATA
ENDBUSRES

RXSETUP:
00 05 01 00 00 00 00 00
EP0: new request - standart Set AddressTX complet

RXSETUP:
80 06 00 01 00 00 12 00
EP0: new request - standart Get Descriptor Device
TX complet
UDP_RXDATA

RXSETUP:
80 06 00 02 00 00 09 00
EP0: new request - standart Get Descriptor Configuration
TX complet
UDP_RXDATA

RXSETUP:
80 06 00 03 00 00 FF 00
EP0: new request - standart Get Descriptor String
TX complet
UDP_RXDATA

RXSETUP:
80 06 03 03 09 04 FF 00
EP0: new request - standart Get Descriptor String
TX complet
UDP_RXDATA

RXSETUP:
80 06 00 02 00 00 FF 00
tring
TX complet
UDP_RXDATA

RXSETUP:
80 06 00 01 00 00 12 00
EP0: new request - standart Get Descriptor Device
TX complet
UDP_RXDATA

RXSETUP:
80 06 00 02 00 00 09 00
EP0: new request - standart Get Descriptor Configuration
TX complet
UDP_RXDATA

RXSETUP:
80 06 00 02 00 00 29 00
EP0: new request - standart Get Descriptor Configuration
TX complet
UDP_RXDATA

RXSETUP:
00 09 01 00 00 00 00 00
EP0: new request - standart Set ConfigurationTX complet
RXSUSP


Т.е. во втором логе отсутствуют запросы класса!!!
Но в обоих случаях проходит стабильная энумерация!!!

Логика подсказывает мне что нужно оставить установку флага AT91C_BASE_UDP->UDP_CSR[0] |= AT91C_UDP_DIR; только после фактической записи в фифо. Хотелось бы услышать мнение знающих людей по всему что я тут написал smile.gif
Go to the top of the page
 
+Quote Post



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

 


RSS Текстовая версия Сейчас: 21st July 2025 - 09:13
Рейтинг@Mail.ru


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