Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Не могу передать пакеты хосту по усб
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Bulat
Использую стандартную прошивку AT91SAM7S256-USART_USB_SAM7S-IAR4_31A-1_00 для связи контроллера с усб, только переписал дескрипторы,
чтобы работала с моим драйвером и убрал код связанный с усарт. Нумерация проходит нормально. Writefile тоже работает. Пакеты благополучно
доставляются моему девайсу. Не могу реализовать передачу пакетов от девайса хосту. Readfile возвращает ошибку.
В стандартной прошивке в файле cdc_enumerate.c я нашел функцию AT91F_UDP_IsConfigured(AT91PS_CDC pCdc), которая, как я понял отвечает за обработку
источников прерываний isr. Туда я добавил свой код, кот обрабатывает прерывания от ер1 и ер2 (ер1 - in, ep2 - out).
Вот этот код:
Код
//*----------------------------------------------------------------------------
//* \fn    AT91F_UDP_IsConfigured
//* \brief Test if the device is configured and handle enumeration
//*----------------------------------------------------------------------------
static uchar AT91F_UDP_IsConfigured(AT91PS_CDC pCdc)
{
    AT91PS_UDP pUDP = pCdc->pUdp;
    AT91_REG isr = pUDP->UDP_ISR;

    if (isr & AT91C_UDP_ENDBUSRES) {
        pUDP->UDP_ICR = AT91C_UDP_ENDBUSRES;
        // reset all endpoints
        pUDP->UDP_RSTEP  = (unsigned int)-1;
        pUDP->UDP_RSTEP  = 0;
        // Enable the function
        pUDP->UDP_FADDR = AT91C_UDP_FEN;
        // Configure endpoint 0
        pUDP->UDP_CSR[0] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);
    }
    else if (isr & AT91C_UDP_EPINT0) {
        pUDP->UDP_ICR = AT91C_UDP_EPINT0;
        AT91F_CDC_Enumerate(pCdc);
    }
             else if (isr & AT91C_UDP_EPINT1){
             pUDP->UDP_ICR = AT91C_UDP_EPINT1;
         pUDP->UDP_CSR[1]=0; //подтверждает, что хост принял данные
             }
                  else if (isr & AT91C_UDP_EPINT2){
                  pUDP->UDP_ICR = AT91C_UDP_EPINT2;
                  AT91F_CDC_ReadData(pCdc);
                  }  
    return pCdc->currentConfiguration;
}


Т.е. при получении данных от хоста возникает прерывание от ер2 и вызывается функция AT91F_CDC_ReadData(pCdc). Ее код приведен ниже:
Код
  extern struct _AT91S_CDC     pCDC;
  static char adrRT[64];
  AT91PS_UDP pUDP = pCdc->pUdp;
  
  pCDC.Read(&pCDC, adrRT,64);
  uint nbytes = AT91F_UDP_Read(pCdc, adrRT, 64);
  pUDP->UDP_CSR[2]=pUDP->UDP_CSR[2]&0x7FFFFFD;/*сброс бита  RX_DATA_BK0 -
подтвердение того, что данные из FIFO считаны*/  
  static char CWord[64];
  CWord[1] = nbytes;
  pCDC.Write(&pCDC,CWord,64);


Т.е. я считываю данные из буфера, а потом пытаюсь передать количество полученных байт обратно на хост, но они не передаются, т.к. device monitoring studio не показывает принятых байт от моего девайса.

Привожу код функции main() из файла main.c
Код
// Enable User Reset and set its minimal assertion to 960 us
     AT91C_BASE_RSTC->RSTC_RMR = AT91C_RSTC_URSTEN | (0x4<<8) | (unsigned int)(0xA5<<24);
    
    // Init USB device
    AT91F_USB_Open();
    // Init USB device
    // Wait for the end of enumeration
    while (!pCDC.IsConfigured(&pCDC));  
    
    while(1);


Как правильно воспользоваться этой стандартной прошивкой, чтобы считывать и записывать данные в конечные точки? Может я свой код не туда добавил, вроде кроме как в AT91F_UDP_IsConfigured(AT91PS_CDC pCdc) и некуда, она же прерывания обрабатывает или я не прав?
Bulat
Всех с Новым Годом! Извиняюсь, что поднимаю тему, но хотелось бы еще раз обратить внимание на свою тему, так ответа пока не нашел.
Заранее благодарен!
DimitryB
Мне кажется, Вы вообще не стой стороны зашли. Почитайте про AIC. И переделайте прерывания .

Только вот тут одна проблема у меня схожая есть. Не возникают эти прерывания на энд-поинтах. А данные передаются. O_o

Функция чтения данных в строчке length = pCDC.Read(&pCDC, data, MSG_SIZE);
Отправки в строчке pCDC.Write(&pCDC, data, length);

Но если пытаться посадить их на прерывания они не срабатывают.

Может, кто знает как их из main {...} в прерывания перенести?
Bulat
Цитата
Может, кто знает как их из main {...} в прерывания перенести?

Да меня это тоже интересует!
DimitryB
Цитата(Bulat @ Jan 3 2008, 21:28) *
Да меня это тоже интересует!


Если вдруг узнаете сообщите плз admin[@]bulkin.info

А для device monitoring studio не поделетесь крякой?
KAlex
Цитата(Bulat @ Dec 29 2007, 10:06) *
Как правильно воспользоваться этой стандартной прошивкой, чтобы считывать и записывать данные в конечные точки? Может я свой код не туда добавил, вроде кроме как в AT91F_UDP_IsConfigured(AT91PS_CDC pCdc) и некуда, она же прерывания обрабатывает или я не прав?

AT91F_UDP_IsConfigured не обрабатывает прерывания.
Сконфигурируйте в main прерывания от EP0, что то типа этого:
if (HID.IsConfigured(&HID)) {
HID.pUdp->UDP_ICR = 0xff00;
AT91F_UDP_DisableIt ( HID.pUdp, 0xFFFF);
AT91F_UDP_EnableIt ( HID.pUdp, AT91C_UDP_EPINT2);
AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_UDP, UDP_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, udp_c_irq_handler);
AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_UDP);}

Обработка прерывания:
__ramfunc __arm void udp_c_irq_handler(void){
AT91PS_UDP pUdp = HID.pUdp;
u_int packetSize, nbBytesRcv = 0, currentReceiveBank = HID.currentRcvBank;
pUdp->UDP_CSR[AT91C_EP_OUT] &= ~(AT91C_UDP_TXCOMP | AT91C_UDP_RXSETUP | AT91C_UDP_ISOERROR );

while (length_in) {
if ( pUdp->UDP_CSR[AT91C_EP_OUT] & (AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1) ) {
packetSize = MIN(pUdp->UDP_CSR[AT91C_EP_OUT] >> 16, length_in);
length_in -= packetSize;
if (packetSize < AT91C_EP_OUT_SIZE)
length_in = 0;
while(packetSize--)
data_in[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT];
pUdp->UDP_CSR[AT91C_EP_OUT] &= ~(currentReceiveBank);
if (currentReceiveBank == AT91C_UDP_RX_DATA_BK0)
currentReceiveBank = AT91C_UDP_RX_DATA_BK1;
else
currentReceiveBank = AT91C_UDP_RX_DATA_BK0;

}
}
// Write_ack(); //Если надо.
HID.currentRcvBank = currentReceiveBank;
}
Bulat
Цитата
А для device monitoring studio не поделетесь крякой?

К сожалению сам пользуюсь 14-дневной версией, вот на работу выйду и надо искать новый комп, чтобы там эту прогу ставить(
Bulat
Цитата(KAlex @ Jan 4 2008, 14:11) *
AT91F_UDP_IsConfigured не обрабатывает прерывания.
Сконфигурируйте в main прерывания от EP0, что то типа этого:
if (HID.IsConfigured(&HID)) {
HID.pUdp->UDP_ICR = 0xff00;
AT91F_UDP_DisableIt ( HID.pUdp, 0xFFFF);
AT91F_UDP_EnableIt ( HID.pUdp, AT91C_UDP_EPINT2);
AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_UDP, UDP_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, udp_c_irq_handler);
AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_UDP);}

Обработка прерывания:
__ramfunc __arm void udp_c_irq_handler(void){
AT91PS_UDP pUdp = HID.pUdp;
u_int packetSize, nbBytesRcv = 0, currentReceiveBank = HID.currentRcvBank;
pUdp->UDP_CSR[AT91C_EP_OUT] &= ~(AT91C_UDP_TXCOMP | AT91C_UDP_RXSETUP | AT91C_UDP_ISOERROR );

while (length_in) {
if ( pUdp->UDP_CSR[AT91C_EP_OUT] & (AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1) ) {
packetSize = MIN(pUdp->UDP_CSR[AT91C_EP_OUT] >> 16, length_in);
length_in -= packetSize;
if (packetSize < AT91C_EP_OUT_SIZE)
length_in = 0;
while(packetSize--)
data_in[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT];
pUdp->UDP_CSR[AT91C_EP_OUT] &= ~(currentReceiveBank);
if (currentReceiveBank == AT91C_UDP_RX_DATA_BK0)
currentReceiveBank = AT91C_UDP_RX_DATA_BK1;
else
currentReceiveBank = AT91C_UDP_RX_DATA_BK0;

}
}
// Write_ack(); //Если надо.
HID.currentRcvBank = currentReceiveBank;
}

Спасибо, но хотелось бы еще посмотреть на пример кода осуществляющий запись данных в конечную точку EP_IN, для передачи их хосту.
Да и еще вопрос. В функции AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_UDP, UDP_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, udp_c_irq_handler) не определены параметры UDP_INTERRUPT_LEVEL и AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE. Где они определяются?
KAlex
Цитата(Bulat @ Jan 9 2008, 09:34) *
Спасибо, но хотелось бы еще посмотреть на пример кода осуществляющий запись данных в конечную точку EP_IN, для передачи их хосту.

__ramfunc __arm u_int AT91F_UDP_Write(AT91PS_HID pCdc, char *pData, u_int length){
AT91PS_UDP pUdp = pCdc->pUdp;
u_int cpt = 0;
if (length)
while ( (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) && !(pUdp->UDP_ISR & AT91C_UDP_RXSUSP) );
// Send the first packet
cpt = MIN(length, FTDI_EP_IN_SIZE);
length -= cpt;
while (cpt--) pUdp->UDP_FDR[AT91C_EP_IN] = *pData++;
pUdp->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY;
while (length) {
// Fill the second bank
cpt = MIN(length, FTDI_EP_IN_SIZE);
length -= cpt;
while ( (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) && !(pUdp->UDP_ISR & AT91C_UDP_RXSUSP) );
if ( pUdp->UDP_ISR & AT91C_UDP_RXSUSP ) return length;
while (cpt--) pUdp->UDP_FDR[AT91C_EP_IN] = *pData++;
// Wait for the the first bank to be sent
while ( !(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) )
if ( !AT91F_UDP_IsConfigured(pCdc) )
return length;
pUdp->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP);
while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);
pUdp->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY;
}
// Wait for the end of transfer
while ( !(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) ){
if ( !AT91F_UDP_IsConfigured(pCdc) )
return length;
};
pUdp->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP);
while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);

return length;
}

Для ускоренной передачи пакетов не более 64 байта:
__ramfunc __arm void AT91F_UDP_Write64(AT91PS_HID pCdc, char *pData, char length){
AT91PS_UDP pUdp = pCdc->pUdp;
while ( (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) && !(pUdp->UDP_ISR & AT91C_UDP_RXSUSP) );
pUdp->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP);

while (length--) pUdp->UDP_FDR[AT91C_EP_IN] = *pData++;
pUdp->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY;
}




Цитата(Bulat @ Jan 9 2008, 09:34) *
Да и еще вопрос. В функции AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_UDP, UDP_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, udp_c_irq_handler) не определены параметры UDP_INTERRUPT_LEVEL и AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE. Где они определяются?

Делается один раз в main:
if (HID.IsConfigured(&HID)) {
HID.pUdp->UDP_ICR = 0xff00;
AT91F_UDP_DisableIt ( HID.pUdp, 0xFFFF);
AT91F_UDP_EnableIt ( HID.pUdp, AT91C_UDP_EPINT2);
AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_UDP, UDP_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, udp_c_irq_handler);
AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_UDP);
}
Bulat
Цитата
Да и еще вопрос. В функции AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_UDP, UDP_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, udp_c_irq_handler) не определены параметры UDP_INTERRUPT_LEVEL и AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE. Где они определяются?QuoteEndQuoteEEndДелается один раз в main: if (HID.IsConfigured(&HID)) { HID.pUdp->UDP_ICR = 0xff00; AT91F_UDP_DisableIt ( HID.pUdp, 0xFFFF); AT91F_UDP_EnableIt ( HID.pUdp, AT91C_UDP_EPINT2); AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_UDP, UDP_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, udp_c_irq_handler); AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_UDP);}


Я именно так и сделал, но компилятор пишет:
Error[Pe020]: identifier "UDP_INTERRUPT_LEVEL" is undefined
Error[Pe020]: identifier "AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE" is undefined

Может просто вместо этих полей конкретные числа поставить? Вот только какие?
KAlex
Цитата(Bulat @ Jan 11 2008, 11:32) *
Я именно так и сделал, но компилятор пишет:
Error[Pe020]: identifier "UDP_INTERRUPT_LEVEL" is undefined
Error[Pe020]: identifier "AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE" is undefined

Может просто вместо этих полей конкретные числа поставить? Вот только какие?

AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE определен в AT91SAM7Sххх.h
UDP_INTERRUPT_LEVEL определяешь сам.
Bulat
Может я неправильно вызываю функцию записи UDP_Write() в обработчике прерывания? (пытаюсь передать 64 байт). На всякий случай привожу код с main:
Код
#define MSG_SIZE                 1000
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define AT91C_EP_IN_SIZE 0x40
#define UDP_INTERRUPT_LEVEL 0x7
//*--------------------------------------------------------------------------------------
//* Function Name       : main
//* Object              :
//*--------------------------------------------------------------------------------------
int main ( void )
{
  __ramfunc __arm void udp_c_irq_handler(void);  
  // Enable User Reset and set its minimal assertion to 960 us
     AT91C_BASE_RSTC->RSTC_RMR = AT91C_RSTC_URSTEN | (0x4<<8) | (unsigned int)(0xA5<<24);
    
    // Init USB device
    AT91F_USB_Open();
    // Init USB device
    // Wait for the end of enumeration
    while (!pCDC.IsConfigured(&pCDC));  
    pCDC.pUdp->UDP_ICR = 0xff00;
    AT91F_UDP_DisableIt ( pCDC.pUdp, 0xFFFF);
    AT91F_UDP_EnableIt (pCDC.pUdp, AT91C_UDP_EPINT2);
    AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_UDP, UDP_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, udp_c_irq_handler);
    AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_UDP);
  
  
}

//udp_c_irq_handler
    __ramfunc __arm void udp_c_irq_handler(void)
    {
      char buff_r[64];
      static char buff_w[64];
      pCDC.Write = UDP_Write;      
      pCDC.Read = UDP_Read;    
      
      unsigned int ret_val = pCDC.Read(&pCDC, buff_r,64);
      for(int i=0;i<64;i++)
      {
        buff_w[i] = i;
      }  
      pCDC.Write(&pCDC, buff_w,64);
    
    
    }    

//*----------------------------------------------------------------------------
//* \fn    UDP_Read
//* \brief Read available data from Endpoint OUT 2
//*----------------------------------------------------------------------------
__ramfunc __arm unsigned int UDP_Read(AT91PS_CDC pCdc, char *data_in, unsigned int length_in)
{      
      AT91PS_UDP pUdp = pCDC.pUdp;      
      unsigned int packetSize, nbBytesRcv = 0, currentReceiveBank = pCDC.currentRcvBank;
      pUdp->UDP_CSR[AT91C_EP_OUT] &= ~(AT91C_UDP_TXCOMP | AT91C_UDP_RXSETUP | AT91C_UDP_ISOERROR );
      
      while (length_in)
      {
        if ( pUdp->UDP_CSR[AT91C_EP_OUT] & (AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1) ) {
        packetSize = MIN(pUdp->UDP_CSR[AT91C_EP_OUT] >> 16, length_in);
        length_in -= packetSize;
        if (packetSize < AT91C_EP_OUT_SIZE)
        length_in = 0;
        while(packetSize--)
        data_in[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT];
        pUdp->UDP_CSR[AT91C_EP_OUT] &= ~(currentReceiveBank);
        if (currentReceiveBank == AT91C_UDP_RX_DATA_BK0)
        currentReceiveBank = AT91C_UDP_RX_DATA_BK1;
        else
        currentReceiveBank = AT91C_UDP_RX_DATA_BK0;
        }
      }
       pCDC.currentRcvBank = currentReceiveBank;
      return nbBytesRcv;
}

//*----------------------------------------------------------------------------
//* \fn    UDP_Write
//* \brief Send through endpoint 1
//*----------------------------------------------------------------------------
__ramfunc __arm unsigned int UDP_Write(AT91PS_CDC pCdc, const char *pData, unsigned int length)
{
    AT91PS_UDP pUdp = pCdc->pUdp;
unsigned int cpt = 0;
if (length)
while ( (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) && !(pUdp->UDP_ISR & AT91C_UDP_RXSUSP) );
// Send the first packet
cpt = MIN(length, AT91C_EP_IN_SIZE);
length -= cpt;
while (cpt--) pUdp->UDP_FDR[AT91C_EP_IN] = *pData++;
pUdp->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY;
while (length) {
// Fill the second bank
cpt = MIN(length, AT91C_EP_IN_SIZE);
length -= cpt;
while ( (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) && !(pUdp->UDP_ISR & AT91C_UDP_RXSUSP) );
if ( pUdp->UDP_ISR & AT91C_UDP_RXSUSP ) return length;
while (cpt--) pUdp->UDP_FDR[AT91C_EP_IN] = *pData++;
// Wait for the the first bank to be sent
while ( !(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) )
//if ( !AT91F_UDP_IsConfigured(pCdc) )
//return length;
pUdp->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP);
while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);
pUdp->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY;
}
// Wait for the end of transfer
while ( !(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) ){
//if ( !AT91F_UDP_IsConfigured(pCdc) )
//return length;
};
pUdp->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP);
while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);

return length;
}
Bulat
Помоему даже обработчик прерываний udp_c_irq_handler не вызывается...
Вроде прерывания инициализировал так, как мне тут объяснили. Еще раз привожу функцию main и функциюобработчика прерваний. Посмотрите, пжста, почему у меня прерывания не вызываются от EP_OUT?
Код
#define MSG_SIZE                 1000
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define AT91C_EP_IN_SIZE 0x40
#define UDP_INTERRUPT_LEVEL 0x7
//*--------------------------------------------------------------------------------------
//* Function Name       : main
//* Object              :
//*--------------------------------------------------------------------------------------
int main ( void )
{
  __ramfunc __arm void udp_c_irq_handler(void);  
  // Enable User Reset and set its minimal assertion to 960 us
     AT91C_BASE_RSTC->RSTC_RMR = AT91C_RSTC_URSTEN | (0x4<<8) | (unsigned int)(0xA5<<24);    
    // Init USB device
    AT91F_USB_Open();
    // Init USB device
    // Wait for the end of enumeration
    while (!pCDC.IsConfigured(&pCDC));  
    pCDC.pUdp->UDP_ICR = 0xff00;
    AT91F_UDP_DisableIt ( pCDC.pUdp, 0xFFFF);
    AT91F_UDP_EnableIt (pCDC.pUdp, AT91C_UDP_EPINT2);
    AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_UDP, UDP_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, udp_c_irq_handler);
    AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_UDP);  
}

//udp_c_irq_handler
    __ramfunc __arm void udp_c_irq_handler(void)
    {
      char buff_r[64];
      static char buff_w[64];
      pCDC.Write = UDP_Write;      
      pCDC.Read = UDP_Read;          
      
      pCDC.Read(&pCDC, buff_r,64);
      
      for(int i=0;i<64;i++)
      {
        buff_w[i] = i;
      }  
      pCDC.Write(&pCDC, buff_w,64);    
    
    }

Заранее благодарен!
Сергей Борщ
Цитата(Bulat @ Jan 15 2008, 13:06) *
Помоему даже обработчик прерываний udp_c_irq_handler не вызывается...
А где сам обработчик IRQ? Что-то вроде
Код
#pragma vector = 0x18
__irq __arm void IRQ_Switch()
{
    void (*Handler)() = (void(*)())AT91C_BASE_AIC->AIC_IVR;
    Handler();
    AT91C_BASE_AIC->AIC_EOICR = 0;                    // Reset AIC logic
}
Где в main() глобальное разрешение разрешение прерываний ( __enable_interrupt(); )?

хотя, возможно вы это просто не показали, тогда извиняюсь.
Bulat
Цитата
А где сам обработчик IRQ? Что-то вроде c1ec1#pragma vector = 0x18__irq __arm void IRQ_Switch() {    void (*Handler)() = (void(*)())AT91C_BASE_AIC->AIC_IVR;    Handler();    AT91C_BASE_AIC->AIC_EOICR = 0;                    // Reset AIC logic}c2ec2Где в main() глобальное разрешение разрешение прерываний ( __enable_interrupt(); )?хотя, возможно вы это просто не показали, тогда извиняюсь.


Если я добавляю обработчик IRQ, девайс вообще перестает определяться! Я же за основу взял готовый пример USB-USART вот и пытаюсь его под себя переделать.
Вот как выглядит код с обработчиком IRQ, с main и самим хандлером:
Код
#pragma vector = 0x18
__irq __arm void IRQ_Switch()
{
    void (*udp_c_irq_handler)() = (void(*)())AT91C_BASE_AIC->AIC_IVR;
    udp_c_irq_handler();
    AT91C_BASE_AIC->AIC_EOICR = 0;                    // Reset AIC logic
}

int main ( void )
{
  __ramfunc __arm void udp_c_irq_handler(void);  
  // Enable User Reset and set its minimal assertion to 960 us
     AT91C_BASE_RSTC->RSTC_RMR = AT91C_RSTC_URSTEN | (0x4<<8) | (unsigned int)(0xA5<<24);    
    // Init USB device
    AT91F_USB_Open();
    // Init USB device
    // Wait for the end of enumeration
    while(!pCDC.IsConfigured(&pCDC));
    
    AT91C_BASE_AIC->AIC_IECR |= (1<<AT91C_ID_UDP);
    AT91C_BASE_AIC->AIC_IDCR = ~AT91C_BASE_AIC->AIC_IECR;
    
    pCDC.pUdp->UDP_ICR = 0xff00;
    AT91F_UDP_DisableIt ( pCDC.pUdp, 0xFFFF);
    AT91F_UDP_EnableIt (pCDC.pUdp, AT91C_UDP_EPINT2);
    AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_UDP, UDP_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_HIGH_LEVEL, udp_c_irq_handler);
    AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_UDP);  
}

//udp_c_irq_handler
    __ramfunc __arm void udp_c_irq_handler(void)
    {
      char buff_r[64];
      static char buff_w[64];
      //pCDC.Write = UDP_Write;      
      //pCDC.Read = UDP_Read;
      
      unsigned int ret_val = UDP_Read(&pCDC, buff_r,64);
      for(int i=0;i<64;i++)
      {
        buff_w[i] = i;
      }  
      UDP_Write(&pCDC, buff_w,64);    
    }

Т.е. добавив обработчик __irq __arm void IRQ_Switch() девайс перестает даже нумероваться! Почему?
DimitryB
Потому что он у вас уходит в прерывание по END BUS RESET и вы не сбрасываете прерывание В итоге оно все время повторяется и enumeration устройства так и не происходит.

Вы должны знать как использовать прерывание:
1. Объявить прерывание задав соответствующим регистрам 1-цы:
AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_UDP, UDP_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_HIGH_LEVEL, udp_c_irq_handler);

2. Активировать прерывания
AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_UDP);

3. В процедуре udp_c_irq_handler установить какое прерывание сработало

4. По окончании вызова процедуры сбросить прерывание в его статус-регистре иначе оно будет повторяться вновь и вновь

Вот Вам еще подсказка Это сбрасывает прерывание

//Clear interruptions by:
// 1. USB Resume Interrupt 2. USB End Of Bus Reset Interrupt
// because they traps programm inside this subrounte
AT91F_UDP_InterruptClearRegister(AT91C_BASE_UDP, AT91C_UDP_RXRSM);
AT91F_UDP_InterruptClearRegister(AT91C_BASE_UDP, AT91C_UDP_ENDBUSRES);
//AT91F_UDP_InterruptClearRegister clears Interrupt Register

А это функция из библиотеки
__inline void AT91F_UDP_InterruptClearRegister (
AT91PS_UDP pUDP, // \arg pointer to UDP controller
unsigned int flag) // \arg IT to be clear
{
pUDP->UDP_ICR = flag;
}

библиотека зовется lib_AT91SAM7S64.h
Bulat
Цитата
DimitryB Дата Сегодня, 05:01
Потому что он у вас уходит в прерывание по END BUS RESET и вы не сбрасываете прерывание В итоге оно все время повторяется и enumeration устройства так и не происходит.

Вы должны знать как использовать прерывание...


То, что вы перечислили все у меня прописано в функции main. Я же взял за основу готовый пример USART_USB, поэтому нумерация у меня проходит нормально. Я говорил о том, что когда добавлял код
Код
#pragma vector = 0x18
__irq __arm void IRQ_Switch()
{
    void (*udp_c_irq_handler)() = (void(*)())AT91C_BASE_AIC->AIC_IVR;
    udp_c_irq_handler();
    AT91C_BASE_AIC->AIC_EOICR = 0;                    // Reset AIC logic
}

в файл main.c нумерация переставала работать, но это логично, так как в udp_c_irq_handler(); я же не обрабатываю прерывание от ep0. Прерывание от ep0 или от END BUS RESET определяются в функции AT91F_UDP_IsConfigured(AT91PS_CDC pCdc), которая прописана в файле cdc_enumerate.c, там же и происходит нумерация. Я же ожидаю окончание нумерации в функции main файла main.c:
Код
while(!pCDC.IsConfigured(&pCDC));

Только после этого я инициализирую обработчик прерывания от ep2. При этом я сначала сбрасываю (!!!) все прерывания:
Код
pCDC.pUdp->UDP_ICR = 0xff00;

А потом уже произвожу инициализацию прерывания от ep2 и глобально его разрешаю:
Код
AT91F_UDP_DisableIt ( pCDC.pUdp, 0xFFFF);
AT91F_UDP_EnableIt (pCDC.pUdp, AT91C_UDP_EPINT2);
AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_UDP, UDP_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_HIGH_LEVEL, udp_c_irq_handler);
AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_UDP);

Проблема заключается в том, что в итоге при запросе с компа на чтение данных с моего девайса (функция readfile()) прерывание от ep2 (ep_out) в моем девайсе не возникает, т.е. функция udp_c_irq_handler() не вызывается!

Еще раз привожу функции main и udp_c_irq_handler и обращаю внимание, что нумерация проходит нормально, устройство инициализируется компом, драйвер рабочий, проверяли.
Код
int main ( void )
{
  __ramfunc __arm void udp_c_irq_handler(void);  
  // Enable User Reset and set its minimal assertion to 960 us
     AT91C_BASE_RSTC->RSTC_RMR = AT91C_RSTC_URSTEN | (0x4<<8) | (unsigned int)(0xA5<<24);    
    // Init USB device
    AT91F_USB_Open();
    // Init USB device
    // Wait for the end of enumeration
    while(!pCDC.IsConfigured(&pCDC));    
    pCDC.pUdp->UDP_ICR = 0xff00;
    AT91F_UDP_DisableIt ( pCDC.pUdp, 0xFFFF);
    AT91F_UDP_EnableIt (pCDC.pUdp, AT91C_UDP_EPINT2);
    AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_UDP,   UDP_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_HIGH_LEVEL, udp_c_irq_handler);
    AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_UDP);  
}

//udp_c_irq_handler
    __ramfunc __arm void udp_c_irq_handler(void)
    {      
      int sio = pCDC.pUdp->UDP_ISR&0x7;
      if(sio==0x4) //если прерывание от ep2
      {
        char buff_read[64];
        static char buff_write[64];      
        unsigned int return_val = UDP_Read(&pCDC, buff_read,64);
        for(int i=0;i<64;i++)
        {
          buff_write[i] = i;
        }  
        UDP_Write(&pCDC, buff_write,64);
      }
      pCDC.pUdp->UDP_ICR = 0xff00;
    }
Dron_Gus
Цитата(Bulat @ Jan 17 2008, 08:00) *
Проблема заключается в том, что в итоге при запросе с компа на чтение данных с моего девайса (функция readfile()) прерывание от ep2 (ep_out) в моем девайсе не возникает, т.е. функция udp_c_irq_handler() не вызывается!




А какое прерывание Вы ожидаете? Хост прочитает ваши данные, только если Вы их предварительно положили в FIFO и взвели бит TXPKTRDY.

nameless
2 Bulat по поводу AT91F_enable_interrupt()

для пятого иара так делел в проект включил асм-файл

SECTION text:CODE:NOROOT(2) //RAM
CODE32
IRQ_MASK DEFINE 0x00000080
FIQ_MASK DEFINE 0x00000040
INTs_MASK DEFINE (IRQ_MASK | FIQ_MASK)
PUBLIC AT91F_enable_interrupt
AT91F_enable_interrupt
mrs r0,CPSR
bic r0,r0,#INTs_MASK
msr CPSR_c,r0
bx lr

PUBLIC AT91F_disable_interrupt
AT91F_disable_interrupt
mrs r0,CPSR
orr r0,r0,#INTs_MASK
msr CPSR_c,r0
mrs r0,CPSR
ands r0,r0,#INTs_MASK
beq AT91F_disable_interrupt
bx lr
END

и в соответствующем хедере прописал
extern "C" __ramfunc void AT91F_enable_interrupt(void);
extern "C" __ramfunc void AT91F_disable_interrupt(void);
Bulat
Цитата
nameless Дата Jan 18 2008, 07:17
2 Bulat по поводу AT91F_enable_interrupt()

для пятого иара так делел в проект включил асм-файл

SECTION text:CODE:NOROOT(2) //RAM
CODE32
IRQ_MASK DEFINE 0x00000080
FIQ_MASK DEFINE 0x00000040
INTs_MASK DEFINE (IRQ_MASK | FIQ_MASK)
PUBLIC AT91F_enable_interrupt
AT91F_enable_interrupt
mrs r0,CPSR
bic r0,r0,#INTs_MASK
msr CPSR_c,r0
bx lr

PUBLIC AT91F_disable_interrupt
AT91F_disable_interrupt
mrs r0,CPSR
orr r0,r0,#INTs_MASK
msr CPSR_c,r0
mrs r0,CPSR
ands r0,r0,#INTs_MASK
beq AT91F_disable_interrupt
bx lr
END


Я включил в проект этот asm файл, только при компиляции в нем почти в каждой строчке ошибки: Bad instruction, Bad label. Т.е. ошибки в каждой asm-команде. Может проект я не настроил, хотя это не должно влиять?
Bulat
Да, и, помоему, то что приведено в этом асме описано в Cstartup.s79...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.