|
Код получения прерывания от RXSETUP на SAM7S |
|
|
|
Nov 20 2009, 08:02
|
Частый гость
 
Группа: Участник
Сообщений: 103
Регистрация: 21-06-09
Пользователь №: 50 494

|
Добрый день. Посмотрите пожалуйста код. Ожидается, что при получении 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 все равно не работает. Вроде бы все указал... Затык. Спасибо.
Причина редактирования: Уменьшение видимого объема цитаты исходника.
|
|
|
|
|
Nov 20 2009, 11:00
|
Частый гость
 
Группа: Участник
Сообщений: 103
Регистрация: 21-06-09
Пользователь №: 50 494

|
Цитата Почему бы не взять за основу какой-нибудь атмеловский пример по работе с USB? Запустить его, посмотреть как он работает, а затем уже дорабатывать под свои нужды. Там пока дойдет дело до RXSETUP, надо еще кучу событий обработать. Я бы рад, но как атмеловские проекты под IAR запустить в Keil`e? А через IAR не могу, ибо имею Ulink, который Keil only. Приходится разгребать самому. Я так понимаю, что после подключения устройства к USB порту, хост отсылает Control пакет на который USB-устройство должно ответить. До ответа я еще не дошел, но хочу зафиксировать принятие этого пакета. Намекните, какие еще события должны произойти до этого? Цитата(sergeeff @ Nov 20 2009, 13:50)  Глобальная переменная i первоначально не инициализирована. Это так, к сведению. Согласно ИсточникуЦитата 2. Глобальные переменные всегда инициализируются, и если это не сделано явно, то они инициализируются нулевым значением. Или это не правда?
Сообщение отредактировал Shaienn - Nov 20 2009, 11:03
|
|
|
|
|
Nov 20 2009, 11:04
|

Местный
  
Группа: Свой
Сообщений: 426
Регистрация: 20-01-05
Из: Зеленоград
Пользователь №: 2 070

|
Цитата(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
|
|
|
|
|
Nov 25 2009, 04:16
|
Частый гость
 
Группа: Участник
Сообщений: 103
Регистрация: 21-06-09
Пользователь №: 50 494

|
2vmp Спасибо за ссылку. Куча откровений  Цитата(aaarrr @ Nov 23 2009, 10:04)  Вообще-то задолго до RXSETUP случится ENDBUSRES, который этот самый RXSETUP успешно запретит. Это уже стало понятно  В процессе разбирания USB, понял следующее. 1) Подключаем подтяжку к D+, с этого момента хост считает, что устройство присоединено. 2) Хост производит процедуру сброса, после которой возникает флаг ENDBUSRES. В связи с этим следующие вопросы: 1) Я так понимаю, что прерывание ENDBUSRES нигде в регистрах разрешения прерываний не объявляется и прерывание разрешено изначально? 2) Почему-то в моем Keil нет возможности при отладке заглянуть в регистры UDP и в AIC нет регистра прерывания UDP. Это лечится?
|
|
|
|
|
Nov 25 2009, 10:40
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(Shaienn @ Nov 25 2009, 07:16)  1) Я так понимаю, что прерывание ENDBUSRES нигде в регистрах разрешения прерываний не объявляется и прерывание разрешено изначально? Да. Цитата(Shaienn @ Nov 25 2009, 07:16)  2) Почему-то в моем Keil нет возможности при отладке заглянуть в регистры UDP и в AIC нет регистра прерывания UDP. Это лечится? Регистр прерывания UDP никакого отношения к AIC'у не имеет.
|
|
|
|
|
Nov 25 2009, 12:33
|
Частый гость
 
Группа: Участник
Сообщений: 103
Регистрация: 21-06-09
Пользователь №: 50 494

|
Цитата(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; } Может я чего-то не понимаю?
|
|
|
|
|
Nov 25 2009, 14:18
|
Частый гость
 
Группа: Участник
Сообщений: 103
Регистрация: 21-06-09
Пользователь №: 50 494

|
Цитата(aaarrr @ Nov 25 2009, 18:12)  В AIC заводится только сигнал прерывания UDP, точно так же, как и сигналы другой периферии. Какой "регистр прерывания UDP" вы хотите там увидеть? Я неправильно выразился. Когда отлаживал прерывания разной периферии, Keil позволял посмотреть, все ли настройки установились и позволял увидеть вектор прерывания для данной периферии, но вот UDP в списке периферии Keil-а нет.
|
|
|
|
|
Nov 29 2009, 15:51
|
Частый гость
 
Группа: Участник
Сообщений: 103
Регистрация: 21-06-09
Пользователь №: 50 494

|
Здравствуйте. Поправьте меня в процессе отправки дескриптора. 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 устройство работает неправильно. Если хост требует дескриптор устройства снова и снова это значит, что я ему отправляю что-то неправильное? Вроде, все как завещано.
|
|
|
|
|
Nov 29 2009, 17:51
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(Shaienn @ Nov 29 2009, 18:51)  Почему такая штука? Потому что по спецификации хост может запросить много. А отправить вы должны не более чем запрошено. Цитата(Shaienn @ Nov 29 2009, 18:51)  Если хост требует дескриптор устройства снова и снова это значит, что я ему отправляю что-то неправильное? Вроде, все как завещано. Значит неправильно отправляете - не вовремя снимаете RXSETUP, не вовремя или неправильно ставите DIR и т.п.
|
|
|
|
|
Nov 30 2009, 11:12
|
Частый гость
 
Группа: Участник
Сообщений: 103
Регистрация: 21-06-09
Пользователь №: 50 494

|
Тогда посмотрите пожалуйста код: 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 ] для оформления объемных цитат исходников, самостоятельно редактируя их так, чтобы страницу не "распирало". Я Вам не нянька, чтобы редактировать за Вас оформление Ваших же исходников!
Причина редактирования: Нарушение п.3.4 Правил форума.
|
|
|
|
|
Nov 30 2009, 11:56
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Код, я бы сказал, малость раздутый. Поле size действительно равно восьми? Есть явная ошибка, которая проявится, если размер передаваемых данных будет кратен размеру endpoint'а - в этом случае в конце не будет передан пакет нулевой длины. И зачем вот это: Код if (count!=0){return;} count++; И аккуратнее с атмеловскими примерами, макросы SET_CSR и CLEAR_CSR - это просто безобразие.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|