реклама на сайте
подробности

 
 
> Не могу передать пакеты хосту по усб, at91sam7s256
Bulat
сообщение Dec 29 2007, 07:06
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



Использую стандартную прошивку 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) и некуда, она же прерывания обрабатывает или я не прав?
Go to the top of the page
 
+Quote Post
2 страниц V  < 1 2  
Start new topic
Ответов (15 - 20)
DimitryB
сообщение Jan 17 2008, 00:01
Сообщение #16





Группа: Новичок
Сообщений: 4
Регистрация: 19-07-07
Пользователь №: 29 255



Потому что он у вас уходит в прерывание по 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
Go to the top of the page
 
+Quote Post
Bulat
сообщение Jan 17 2008, 05:00
Сообщение #17


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



Цитата
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;
    }
Go to the top of the page
 
+Quote Post
Dron_Gus
сообщение Jan 17 2008, 14:09
Сообщение #18


Профессионал
*****

Группа: Свой
Сообщений: 1 202
Регистрация: 9-01-05
Из: Санкт-Петербург
Пользователь №: 1 861



Цитата(Bulat @ Jan 17 2008, 08:00) *
Проблема заключается в том, что в итоге при запросе с компа на чтение данных с моего девайса (функция readfile()) прерывание от ep2 (ep_out) в моем девайсе не возникает, т.е. функция udp_c_irq_handler() не вызывается!




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



--------------------
Если сверху смотреть, то сбоку кажется, что снизу ничего не видно.
Go to the top of the page
 
+Quote Post
nameless
сообщение Jan 18 2008, 02:17
Сообщение #19


Частый гость
**

Группа: Свой
Сообщений: 174
Регистрация: 9-07-04
Пользователь №: 305



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);
Go to the top of the page
 
+Quote Post
Bulat
сообщение Jan 22 2008, 04:56
Сообщение #20


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



Цитата
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-команде. Может проект я не настроил, хотя это не должно влиять?
Go to the top of the page
 
+Quote Post
Bulat
сообщение Jan 22 2008, 06:30
Сообщение #21


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



Да, и, помоему, то что приведено в этом асме описано в Cstartup.s79...
Go to the top of the page
 
+Quote Post

2 страниц V  < 1 2
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 07:13
Рейтинг@Mail.ru


Страница сгенерированна за 0.01506 секунд с 7
ELECTRONIX ©2004-2016