Требуется программист в Зеленограде
- обработка данных с датчиков; ColdFire; 40 тыс. e-mail:jobsmp@pochta.ru |
Почему прием пакетов usb в филипсах устроен так мудрено. В частности, ожидание подтверждения приема пакета. Организуем принятие пакета поллингом(IAR 4.41, названия регистров изменены на наглядные)
В документации ЧЕТКО говорится что прерываение EP_0TX возникает после приема ACK (либо NAK тоже, по установкам) от исходящего пакета. Ждемс:
Код(1): Хаххаха, мы повисли Вот этот код да, правильный: Код (2): while PROTOCOL_ENG_CMD(SELECT_EP_CLEAR_INTR+CTRL_ENP_IN); ENDOINT_INTERRUPT_CLEAR=TX0_EP_FLAG; //это прерывание больние НИГДЕ в програме не сбрасывается (вроде бы логично, ведь сюда мы приходим только когда оно появилось. А если мы ушли по return из цикла while, а потом только этот флаг появился? В следующий раз когда этот код получит управление, будет ложное подтверждение исходящего пакета, так? Казалось бы, мы ждем первого из двух условий: освобождения передающего буфера или приема подтверждения в ENDPOIT_INT_STATUS. Однако Код(3): while ((ENDOINT_INTERRUPT_STAT & CTRL_ENP_IN_FLAG)==0)\ Код(4): while ( (ENDOINT_INTERRUPT_STAT & CTRL_ENP_IN_FLAG))==0) замена строчки с if на ENDPOINT_INTR_CLEAR=CTRL_EP_OUT_FLAG; ничего не дает, хотя по идее такая команда должна автоматически вызывать строчку с if в (3) коде, и убирать условие "невозможно отправить пакет из-за пришедшего SETUP", а соответственно создавать условие для установки ENDOINT_INTERRUPT_STAT_bit.TX_0EP Опять не то! Да что же ему надо. Отдельный внутренний флаг прерывания, который станавливает PROTOCOL_ENG_CMD (SELECT_EP_CLEAR_INTR | CTRL_ENP_IN); во втором коде сбрасывает флаг в ENDPIONT_INTR_STATUS? Нет. Что же это за мистический internal interrupt в загадочном time domain и почему программист должен копипастить чужой код когда есть документация. Может я конечно просто такой тупой тупей тупого, привык к легкой жизни на атмеловской документации.
..
while( ((ENDPOINT_INTERRUPT & (1<
..
((ENDOINT_INTERRUPT_STAT&CTRL_ENP_IN_FLAG))==0)
{
if ((PROTOCOL_ENG_CMD (SELECT_EP+CTRL_ENP_IN)\
& BUFFER_FULL_FLAG) == 0)
{
if((ENDOINT_INTERRUPT_STAT&CTRL_ENP_IN_FLAG)==0)//***
{
PROTOCOL_ENG_CMD(SELECT_EP_CLEAR_INTR|CTRL_ENP_IN);
return;
}
}
}
*** - зачем эта строчка, ведь если буффер освободился, это не значит, что уже пришел ответ, да и какая разница пришел или нет, ведь мы проверяем то, что как бы первичней
|| (PROTOCOL_ENG_CMD (SELECT_EP | CTRL_ENP_IN) & BUFFER_FULL_FLAG) == 0 )
не работает! Как это понимать? Уфф,читаем документацию внимательней. Ага, вот оно: пакет по control pipe не будет отправлен если пришел SETUP. Ладно:
if ((PROTOCOL_ENG_CMD (SELECT_EP + CTRL_ENP_OUT) &\ PAKET_OVERWRITTEN_FLAG) break;// (или return)
В модуле есть понятие - usb clock domain. Вот это окончательно все путает. Что за временнОе измерение? Из-за процессов синхронизации прерывание в системную шину приходит позже? Нет, иначе бы работал первый код.
ENDP_INT_STATUS, и без снятия которого невозможно сбросить соотв. флаг в ENDP_INT_STATUS? Почему тогда работает второй код, хотя в программе установлен флаг EP_0TX в ENDP_INTR_ENABLE, а в обработчике прерываний его обработка даже не предусмотрена, и он не сбрасывается каким либо киллером вроде ENDPINTCLR=0xFFFF. Получается что строчка
Кстати смотрим еррдату - ничего подобного в списке косяков нету, а сама еррдата относится к ревизиям чипов A, B и . У меня марировка нижняя строчка "ZPG0541-Y" - значит ревизия "Y", ни одна из трех вышеприведенных хехе.
Далее: команда validate buffer - сбросить выхоной буфер в шину. Но команда не работает если НЕПОСРЕДСТВЕННО перед ней не призвести select endpoint. Смотрим - select endpoint да, переведит внутренний указатель на начало буфера. Но эта последовательность четко не указывается! И я должен об этом догадываться опосредованно. Ведь нигде толком не описана внутренняя логика это долбаного protocol engine. Может это и есть он самый - большой собачий секрет?
Ответы