Перейти к содержанию
    

Код получения прерывания от RXSETUP на SAM7S

Добрый день. Посмотрите пожалуйста код. Ожидается, что при получении Control пакета возникнет бит RXSETUP и будет вызвано прерывание isrUDP, но в прерывание не заходит.

 

#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 все равно не работает.

 

Вроде бы все указал... Затык.

 

 

Спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Почему бы не взять за основу какой-нибудь атмеловский пример по работе с USB?

Запустить его, посмотреть как он работает, а затем уже дорабатывать под свои нужды.

Там пока дойдет дело до RXSETUP, надо еще кучу событий обработать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Почему бы не взять за основу какой-нибудь атмеловский пример по работе с USB?

Запустить его, посмотреть как он работает, а затем уже дорабатывать под свои нужды.

Там пока дойдет дело до RXSETUP, надо еще кучу событий обработать.

 

Я бы рад, но как атмеловские проекты под IAR запустить в Keil`e? А через IAR не могу, ибо имею Ulink, который Keil only. Приходится разгребать самому.

 

Я так понимаю, что после подключения устройства к USB порту, хост отсылает Control пакет на который USB-устройство должно ответить. До ответа я еще не дошел, но хочу зафиксировать принятие этого пакета.

Намекните, какие еще события должны произойти до этого?

 

Глобальная переменная i первоначально не инициализирована. Это так, к сведению.

Согласно Источнику

2. Глобальные переменные всегда инициализируются, и если это не сделано явно, то они инициализируются нулевым значением.

 

Или это не правда?

Изменено пользователем Shaienn

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я бы рад, но как атмеловские проекты под 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ожидается, что при получении Control пакета возникнет бит RXSETUP и будет вызвано прерывание isrUDP, но в прерывание не заходит.

Вообще-то задолго до RXSETUP случится ENDBUSRES, который этот самый RXSETUP успешно запретит.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2vmp

Спасибо за ссылку. Куча откровений :)

 

Вообще-то задолго до RXSETUP случится ENDBUSRES, который этот самый RXSETUP успешно запретит.

Это уже стало понятно :)

 

 

В процессе разбирания USB, понял следующее.

 

1) Подключаем подтяжку к D+, с этого момента хост считает, что устройство присоединено.

2) Хост производит процедуру сброса, после которой возникает флаг ENDBUSRES.

 

В связи с этим следующие вопросы:

1) Я так понимаю, что прерывание ENDBUSRES нигде в регистрах разрешения прерываний не объявляется и прерывание разрешено изначально?

2) Почему-то в моем Keil нет возможности при отладке заглянуть в регистры UDP и в AIC нет регистра прерывания UDP. Это лечится?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1) Я так понимаю, что прерывание ENDBUSRES нигде в регистрах разрешения прерываний не объявляется и прерывание разрешено изначально?

Да.

 

2) Почему-то в моем Keil нет возможности при отладке заглянуть в регистры UDP и в AIC нет регистра прерывания UDP. Это лечится?

Регистр прерывания UDP никакого отношения к AIC'у не имеет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Регистр прерывания 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;
}

 

Может я чего-то не понимаю?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Может я чего-то не понимаю?

В AIC заводится только сигнал прерывания UDP, точно так же, как и сигналы другой периферии. Какой "регистр прерывания UDP" вы хотите там увидеть?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В AIC заводится только сигнал прерывания UDP, точно так же, как и сигналы другой периферии. Какой "регистр прерывания UDP" вы хотите там увидеть?

 

Я неправильно выразился. Когда отлаживал прерывания разной периферии, Keil позволял посмотреть, все ли настройки установились и позволял увидеть вектор прерывания для данной периферии, но вот UDP в списке периферии Keil-а нет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Здравствуйте.

 

Поправьте меня в процессе отправки дескриптора.

 

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 устройство работает неправильно. Если хост требует дескриптор устройства снова и снова это значит, что я ему отправляю что-то неправильное? Вроде, все как завещано.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Почему такая штука?

Потому что по спецификации хост может запросить много. А отправить вы должны не более чем запрошено.

 

Если хост требует дескриптор устройства снова и снова это значит, что я ему отправляю что-то неправильное? Вроде, все как завещано.

Значит неправильно отправляете - не вовремя снимаете RXSETUP, не вовремя или неправильно ставите DIR и т.п.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тогда посмотрите пожалуйста код:

 

/// 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 взял из атмеловского примера:

 

/// 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 ] для оформления объемных цитат исходников, самостоятельно редактируя их так, чтобы страницу не "распирало". Я Вам не нянька, чтобы редактировать за Вас оформление Ваших же исходников! :twak:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Код, я бы сказал, малость раздутый. Поле size действительно равно восьми? Есть явная ошибка, которая проявится, если размер передаваемых данных будет кратен размеру endpoint'а - в этом случае в конце не будет передан пакет нулевой длины.

И зачем вот это:

                        if (count!=0){return;}        
                        count++;

 

И аккуратнее с атмеловскими примерами, макросы SET_CSR и CLEAR_CSR - это просто безобразие.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...