А как реализовать обработку UDP через прерывания? Сделал как в примере USBWorkframe, который вместе с новым ИАРом еще (5.10) вместе идет. Пишу вот так:
Код
// Настраиваем вызов прерываний
AT91F_AIC_ConfigureIt(
AT91C_BASE_AIC,
AT91C_ID_UDP,
USB_INTERRUPT_PRIORITY,
0,
USB_InterruptHandler);
// Включаем прерывание
AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_UDP);
// На какие прерывания реагировать
AT91C_BASE_UDP->UDP_IER |= AT91C_UDP_ENDBUSRES | AT91C_UDP_EPINT0;
Ничего не работает. Винда ждет свой таймаут и говорит, что неизвестное устройство.
А когда пишу вот так, то все работает
Код
int main()
{
.................
.................
USB_Open(&usb);
USB_SetPullUp(1);
while(1)
{
USB_InterruptHandler();
}
}
Что не так с прерываниями?
Вот реализация самой функции USB_InterruptHandler:
Код
// Функция для обработки прерываний USB контроллера
void USB_InterruptHandler()
{
// Считываем значение регистра статуса преривания
AT91_REG ISR = AT91C_BASE_UDP->UDP_ISR;
// Маски прерываний, которые нужно удалить
AT91_REG CSR = 0;
// Обрабатываем все прерывания
while(1)
{
// Маски прерываний, которые нужно удалить
CSR = 0;
// Если завершился сброс USB контроллера
if (ISR & AT91C_UDP_ENDBUSRES)
{
// Очищаем маску этого прерывания
CSR |= AT91C_UDP_ENDBUSRES;
// Reset all endpoints
AT91C_BASE_UDP->UDP_RSTEP = (unsigned int)-1;
AT91C_BASE_UDP->UDP_RSTEP = 0;
// Enable the function
AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN;
// Включаем EndPoint 0 и устанавливаем режим
// передачи данных Control
AT91C_BASE_UDP->UDP_CSR[0] = AT91C_UDP_EPEDS |
AT91C_UDP_EPTYPE_CTRL;
}
// Прерывание от EndPoint 0
// Several signals can generate this interrupt.
// The reason can be found by reading UDP_CSR[0]:
// RXSETUP set to 1
// RX_DATA_BK0 set to 1
// RX_DATA_BK1 set to 1
// TXCOMP set to 1
// STALLSENT set to 1
else if (ISR & AT91C_UDP_EPINT0)
{
// Очищаем маску этого прерывания
CSR |= AT91C_UDP_EPINT0;
// Если хост отправил Setup пакет и он доступен
// в FIFO буфере EndPoint'а 0, то
if((AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_RXSETUP))
{
// Отвечаем на запрос от хоста
USB_RequestHandler();
}
}
// Очищаем маску всех обработанных прерываний
if(CSR)
{
AT91C_BASE_UDP->UDP_ICR = CSR;
}
// Если больше не обработали никаких прерываний, то
if(CSR == 0)
{
// Все прерывания обработаны
break;
}
// Опять считываем значение регистра статуса преривания
AT91_REG ISR = AT91C_BASE_UDP->UDP_ISR;
}
}
P.S. Если чего, то код в функции USB_InterruptHandler не зависает: пробовал нажимать break во время выполнения - вылетал в бесконечный цикл, который в main().