Работаю с контроллером 1986ВЕ1QI и USB.
Не могу понять, должен ли что-то device программно отвечать на запрос хоста SET_ADDRESS (0x00, 0x05, ...)? Или это должно поддерживаться на аппаратном уровне?
Инициализация устройства застревает именно на этом этапе, т.е. первую отсылку дескриптора (запрос 0х80, 0х06, ...) оно вроде как проходит.
Использую лишь некоторые части кода библиотеки, т.к. целиком она тащит за собой кучу всего. По этой причине инициализацию пишу поэтапно, и вот на адресе застрял.
Я знаю, что адрес фактически должен меняться только после ответа на GET_STATUS, но что делать на этапе SET_ADDRESS, чтобы оно дальше пошло?
Подскажите, пожалуйста, пол-дня над этой строчкой думаю.
if (MDR_USB->SIS & RESET_EV) //ñáðîñ USB
{
MDR_USB->SIS=0x1F; //Clear Interrupt Status
MDR_USB->SIM=RESET_IE | TDONE_IE | (USB_SOF_EVENT ? SOF_IE : 0); //Enable interrupts
//Setup Control Endpoint 0
MDR_USB->USB_SEP_FIFO[0].RXFC=1; //Clear RX FIFO EndPoint 0
MDR_USB->USB_SEP_FIFO[0].TXFDC=1; //Clear TX FIFO EndPoint 0
MDR_USB->USB_SEP[0].CTRL=EP_EN | EP_RDY; //Enable Endpoint 0, go to endpoint redy state
//Çàäàåì àäðåñ óñòðîéñòâà (ïåðâîíà÷àëüíî 0 - äëÿ ïîñëåäóþùåãî íàçíà÷åíèÿ)
USB_SetSA(0x00); //Ñáðîñ àäðåñà äëÿ îòâåòà íà øèðîêîâåùàòåëüíûå ïàêåòû
MDR_USB->SIS |=RESET_EV; //î÷èñòêà ôëàãà ñáðîñà
}
if (MDR_USB->SIS & TDONE_EV) //ïðîøëà òðàíçàêöèÿ
{
int num;
MDR_USB->SIS |=TDONE_EV; //î÷èñòêà ôëàãà çàâåðøåíèÿ òðàíçàêöèè
for (num=0; num<USB_EP_NUM; num++) //Ïðîâåðêà äàííûõ â êîíå÷íûõ òî÷êàõ
{
if ((MDR_USB->USB_SEP[num].CTRL &EP_EN)&&(!(MDR_USB->USB_SEP[num].CTRL &EP_RDY)))
//Ïî çàâåðøåíèè òðàíçàêöèè òî÷êà áóäåò íå ãîòîâà
break;
}
while (MDR_USB->USB_SEP[num].STS &0x0F) //îáðàáîòêà îøèáîê
{
//if error ocured
if (MDR_USB->USB_SEP[num].STS &RXO_ERR)
{
//USB_Error_Event(1);
MDR_USB->USB_SEP[num].STS &= ~RXO_ERR;
}
else
{
//USB_Error_Event(0);
MDR_USB->USB_SEP[num].STS &= ~0x0F;
}
}
int val=MDR_USB->USB_SEP[num].TS; //Ïðîâåðêà òèïà òðàíçàêöèè
Endpoint(val);
}
}
void Endpoint(int t_type) {
switch (t_type) {
case SETUP: //Óñòàíîâî÷íàÿ òðàíçàêöèÿ
USB_ReadEP (0, InData);
break;
case RESAVE: //Õîñò ïåðåäàåò äàííûå
USB_ReadEP (0, InData);
break;
case TRANSMIT: //Õîñò îæèäàåò äàííûå
USB_ReadEP (0, InData);
if (InData[0]==0x80 && InData[1]==0x06) //Îòïðàâêà äåñêðèïòîðà
USB_WriteEP(0, DESC1, 64);
if (InData[0]==0x00 && InData[1]==0x05) //Ïîëó÷åíèå àäðåñà
{
DEV_adr = InData[2];
MDR_USB->USB_SEP_FIFO[0].RXFC=1; //Î÷èñòêà ïðèåìíîãî áóôåðà è ãîòîâíîñòü
MDR_USB->USB_SEP[0].CTRL |= EP_RDY;
}
if (InData[0]==0x80 && InData[1]==0x00) //Îòïðàâêà ñòàòóñà è íàçíà÷åíèå àäðåñà óñòðîéñòâà
{
USB_WriteEP(0, STATUS, 2);
USB_SetSA(DEV_adr);
}
break;
default: break;
}
}
Не могу понять, должен ли что-то device программно отвечать на запрос хоста SET_ADDRESS (0x00, 0x05, ...)? Или это должно поддерживаться на аппаратном уровне?
Инициализация устройства застревает именно на этом этапе, т.е. первую отсылку дескриптора (запрос 0х80, 0х06, ...) оно вроде как проходит.
Использую лишь некоторые части кода библиотеки, т.к. целиком она тащит за собой кучу всего. По этой причине инициализацию пишу поэтапно, и вот на адресе застрял.
Я знаю, что адрес фактически должен меняться только после ответа на GET_STATUS, но что делать на этапе SET_ADDRESS, чтобы оно дальше пошло?
Подскажите, пожалуйста, пол-дня над этой строчкой думаю.
Спойлер
void USB_IRQHandler (void) {if (MDR_USB->SIS & RESET_EV) //ñáðîñ USB
{
MDR_USB->SIS=0x1F; //Clear Interrupt Status
MDR_USB->SIM=RESET_IE | TDONE_IE | (USB_SOF_EVENT ? SOF_IE : 0); //Enable interrupts
//Setup Control Endpoint 0
MDR_USB->USB_SEP_FIFO[0].RXFC=1; //Clear RX FIFO EndPoint 0
MDR_USB->USB_SEP_FIFO[0].TXFDC=1; //Clear TX FIFO EndPoint 0
MDR_USB->USB_SEP[0].CTRL=EP_EN | EP_RDY; //Enable Endpoint 0, go to endpoint redy state
//Çàäàåì àäðåñ óñòðîéñòâà (ïåðâîíà÷àëüíî 0 - äëÿ ïîñëåäóþùåãî íàçíà÷åíèÿ)
USB_SetSA(0x00); //Ñáðîñ àäðåñà äëÿ îòâåòà íà øèðîêîâåùàòåëüíûå ïàêåòû
MDR_USB->SIS |=RESET_EV; //î÷èñòêà ôëàãà ñáðîñà
}
if (MDR_USB->SIS & TDONE_EV) //ïðîøëà òðàíçàêöèÿ
{
int num;
MDR_USB->SIS |=TDONE_EV; //î÷èñòêà ôëàãà çàâåðøåíèÿ òðàíçàêöèè
for (num=0; num<USB_EP_NUM; num++) //Ïðîâåðêà äàííûõ â êîíå÷íûõ òî÷êàõ
{
if ((MDR_USB->USB_SEP[num].CTRL &EP_EN)&&(!(MDR_USB->USB_SEP[num].CTRL &EP_RDY)))
//Ïî çàâåðøåíèè òðàíçàêöèè òî÷êà áóäåò íå ãîòîâà
break;
}
while (MDR_USB->USB_SEP[num].STS &0x0F) //îáðàáîòêà îøèáîê
{
//if error ocured
if (MDR_USB->USB_SEP[num].STS &RXO_ERR)
{
//USB_Error_Event(1);
MDR_USB->USB_SEP[num].STS &= ~RXO_ERR;
}
else
{
//USB_Error_Event(0);
MDR_USB->USB_SEP[num].STS &= ~0x0F;
}
}
int val=MDR_USB->USB_SEP[num].TS; //Ïðîâåðêà òèïà òðàíçàêöèè
Endpoint(val);
}
}
void Endpoint(int t_type) {
switch (t_type) {
case SETUP: //Óñòàíîâî÷íàÿ òðàíçàêöèÿ
USB_ReadEP (0, InData);
break;
case RESAVE: //Õîñò ïåðåäàåò äàííûå
USB_ReadEP (0, InData);
break;
case TRANSMIT: //Õîñò îæèäàåò äàííûå
USB_ReadEP (0, InData);
if (InData[0]==0x80 && InData[1]==0x06) //Îòïðàâêà äåñêðèïòîðà
USB_WriteEP(0, DESC1, 64);
if (InData[0]==0x00 && InData[1]==0x05) //Ïîëó÷åíèå àäðåñà
{
DEV_adr = InData[2];
MDR_USB->USB_SEP_FIFO[0].RXFC=1; //Î÷èñòêà ïðèåìíîãî áóôåðà è ãîòîâíîñòü
MDR_USB->USB_SEP[0].CTRL |= EP_RDY;
}
if (InData[0]==0x80 && InData[1]==0x00) //Îòïðàâêà ñòàòóñà è íàçíà÷åíèå àäðåñà óñòðîéñòâà
{
USB_WriteEP(0, STATUS, 2);
USB_SetSA(DEV_adr);
}
break;
default: break;
}
}
