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

 
 
> Рабочий пример работы SL811 в режиме host'a
Hexxx
сообщение Apr 10 2007, 15:14
Сообщение #1


Участник
*

Группа: Свой
Сообщений: 49
Регистрация: 29-03-06
Пользователь №: 15 592



Тема поднималась милион раз, но никто так и не удосужился запостить пример. Значит буду первым:
Код
#define MASTER_MODE             0x80

void SL811_Init(void)
{    
    SL811Write(cDATASet, 0xe0); //SOF Timeout Value
    SL811Write(cSOFcnt, 0x2e | MASTER_MODE);
    SL811Write(CtrlReg, 0x5);            
    SL811Write(EP0Status, PID_SOF);
    SL811Write(EP0Counter, 0);              //Set Endpoint Zero
    SL811Write(EP0Control, 0x01);            //Start the SOF
    SL811Write(IntEna, INSERT_REMOVE);      //USB-A, Insert/Remove, USB_Resume.
    SL811Write(IntStatus, INT_CLEAR);    //Clear Interrupt enable status
    
}

#define NO_ERROR 0
#define ERROR_TIMEOUT 1
#define ERROR_STALL 2
#define ERROR_OVERFLOW 3
#define ERROR_EP0_ERROR 4
#define ERROR_UNKNOWN 5


int SendData(void * pData, int DataSize)
{
  unsigned char result, intr, remainder,timeout;
  SL811BufWrite(EP0_Buf,pData,DataSize);

  SL811Write(EP0Status,(PID_SETUP | 0));  // PID + EP address
  SL811Write(EP0Counter,0);               // USB address
  SL811Write(EP0Address,EP0_Buf);         // buffer address, start with "data0"
  SL811Write(EP0XferLen,DataSize);        // data transfer length
  SL811Write(IntStatus,INT_CLEAR);        // clear interrupt status
  SL811Write(EP0Control,DATA0_WR);  

  timeout=10;
  while(1)
  {
    do
    {                                      
      intr = SL811Read(IntStatus);          // wait for interrupt to be done
      if((intr & USB_RESET) || (intr & INSERT_REMOVE))  //leave if device is removed
        return 1;                  
              
    } while (!(intr & USB_A_DONE)); // interrupt done !!!
  
    SL811Write(IntStatus,INT_CLEAR);         // clear interrupt status
    result = SL811Read(EP0Status);           // read EP0status register
    remainder = SL811Read(EP0Counter);       // remainder value in last pkt xfer
  
    if (result & EP0_ACK)
      return 0;  
    
    if (result & EP0_NAK)                  // NAK Detected
    {                            
        SL811Write(IntStatus,INT_CLEAR);        // clear interrupt status, need to
        SL811Write(EP0Control,DATA0_WR);            // re-arm and request for last cmd, IN token
        result = 0;                                     // respond to NAK status only
    }
    
    if (result & EP0_TIMEOUT)                // TIMEOUT Detected
    {                            
        if(timeout)
        {  
            timeout--;
        }
        else
          return ERROR_TIMEOUT;                    // exit on the timeout detected  
        
        SL811Write(IntStatus,INT_CLEAR);        // clear interrupt status, need to
        SL811Write(EP0Control,DATA0_WR);            // re-arm and request for last cmd again
    }
    
    if (result & EP0_STALL)                  // STALL detected
      return ERROR_STALL;                    // for unsupported request.
    
    if (result & EP0_OVERFLOW)                // OVERFLOW detected
      return ERROR_OVERFLOW;  
    
    if (result & EP0_ERROR)                  // ERROR detected
      return ERROR_EP0_ERROR;
  }
  
  
  return ERROR_UNKNOWN;
}

int GetReply(void * pData, int DataSize)
{
  unsigned char result, intr, remainder,timeout;
  
  SL811Write(EP0Status,(PID_IN | 0));  // PID + EP address
  SL811Write(EP0Counter,0);               // USB address
  SL811Write(EP0Address,EP0_Buf);         // buffer address, start with "data0"
  SL811Write(EP0XferLen,DataSize);        // data transfer length
  SL811Write(IntStatus,INT_CLEAR);        // clear interrupt status
  SL811Write(EP0Control,DATA0_RD);  
  
  timeout=10;
  while(1)
  {
    do
    {                                      
      intr = SL811Read(IntStatus);          // wait for interrupt to be done
      if((intr & USB_RESET) || (intr & INSERT_REMOVE))  //leave if device is removed
        return 1;                  
              
    } while (!(intr & USB_A_DONE)); // interrupt done !!!
  
    SL811Write(IntStatus,INT_CLEAR);         // clear interrupt status
    result = SL811Read(EP0Status);           // read EP0status register
    remainder = SL811Read(EP0Counter);       // remainder value in last pkt xfer
  
    if (result & EP0_ACK)
    {
      if(remainder!=DataSize)              
      {
        SL811BufRead(EP0_Buf, pData, DataSize);
        return 0;
      }
    }
    
    if (result & EP0_NAK)                  // NAK Detected
    {                            
        SL811Write(IntStatus,INT_CLEAR);        // clear interrupt status, need to
        SL811Write(EP0Control,DATA0_WR);            // re-arm and request for last cmd, IN token
        result = 0;                                     // respond to NAK status only
    }
    
    if (result & EP0_TIMEOUT)                // TIMEOUT Detected
    {                            
        if(timeout)
        {  
            timeout--;
        }
        else
          return ERROR_TIMEOUT;                    // exit on the timeout detected  
        
        SL811Write(IntStatus,INT_CLEAR);        // clear interrupt status, need to
        SL811Write(EP0Control,DATA0_WR);            // re-arm and request for last cmd again
    }
    
    if (result & EP0_STALL)                  // STALL detected
      return ERROR_STALL;                    // for unsupported request.
    
    if (result & EP0_OVERFLOW)                // OVERFLOW detected
      return ERROR_OVERFLOW;  
    
    if (result & EP0_ERROR)                  // ERROR detected
      return ERROR_EP0_ERROR;
  }
  
  return ERROR_UNKNOWN;
}

unsigned char Buffer[0x64];
void testSL811(void)
{
  int error;
  SetupPKG pkg;
  pkg.bmRequest=0x80;
  pkg.bRequest=0x06;
  pkg.wValue=0x200;
  pkg.wIndex=0x00;
  pkg.wLength=0xFF00;
  
  SL811ClockInit();
  SL811_Init();
  
  error=SendData(&pkg,sizeof(pkg));
  if (!error)
  {
    error=GetReply(Buffer,0x9);  
  }

}


Код не идеальный, надо доделывать функцию чтения. Он инитит хост в режиме low-speed и позволяет вам послать SETUP пакет GET_DESCRIPTOR и вычитать 9-байтов ответа от Slave устройства. Все нехватающие функции и define есть в cy3662/EZ811 development kit'e. Его можно взять вот тут
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Hexxx
сообщение Apr 23 2007, 12:40
Сообщение #2


Участник
*

Группа: Свой
Сообщений: 49
Регистрация: 29-03-06
Пользователь №: 15 592



Отвечает Александр Друзь!

Payload - это масимальный объем информации, который можно переслать/прочитать за 1 раз.
Регистр EP0Counter - возвращает сколько байт было недочитано. Причем, число которое оттуда возвращается - signed! То есть если вы прочитали EP0Counter, а там 0xFC, это означает что не прочитано -4 байта. То есть вы захотели прочитать 0xC байт а девайс вам ответил 0x10-ю байтами. Получатеся, что еще 4 байта не было вычитано, хотя они есть. А если вы захотели прочитать 0xC, а девайс вам вернул 0x8 байт, то EP0Counter будет = 4. Т.е. вы запросили на 4 байта больше чем ответил девайс.

Как узнать размер Payload для EP0?
Payload обычно можно узнать запросив DEVICE descriptor. Но как его узнать если девайс говорит NAK на запрос DEVICE descriptor'a? Экспериментальным путем. Даже если девайс не поддерживает запрос Device descriptor'a, он поддерживает запрос на CONFIGURATION descriptor в любом случае. Обычно тут девайс выдает большой объем информации. Пробуйте читать ответ и смотрите сколько байт будет недочитано. Начните с 8 и увеличивайте кратно 8: 8, 16, 24, 32, 64. При одном из значений Payload, EP0Counter будет == 0. Это значение и есть payload.

Фишка с чтением ответов девайса, длина которых > payload. Девайс действительно не даст вам прочесть данных больше чем payload, поэтому надо будет сделать еще N чтений. Но! Не пытайтесь дебажить код многократного чтения. Там дается очень короткий промежуток времени для дочитывания остальной части ответа. Когда пытаешься дебажить - первая часть читается нормально, а остальные так и не вычитываются.

Переключение буферов делается для быстроты работы, в один мы читаем с USB, а из второго мы считываем то, что было уже прочитано из USB при предидущем чтении. Про то как надо делать переключение буферов описано в Application Notes см. "double buffer"

Пример в EZ811 DK реально работоспособный. Очень важно делать speed_detect().

P.S. Почитал Application Notes по SL811. Много полезного. Приатачил.

Сообщение отредактировал Hexxx - Apr 23 2007, 12:47
Прикрепленные файлы
Прикрепленный файл  sl811hs_appnote.pdf ( 278.45 килобайт ) Кол-во скачиваний: 471
 
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Hexxx   Рабочий пример работы SL811 в режиме host'a   Apr 10 2007, 15:14
- - Hexxx   Я понял как заставить работать пример из EZ811 DK...   Apr 18 2007, 17:28
- - Hexxx   И все таки он глючит на чтении. Люди помогите, уже...   Apr 19 2007, 14:59
- - Hexxx   Так странно, куча людей. У многих уже проблемы с в...   Apr 20 2007, 11:51
- - Hexxx   Эпопея продолжается. Bulk-transfer не пашет. Отпра...   May 3 2007, 13:07
|- - misyachniy   Не знаю что и посоветовать. У меня был затык в том...   May 3 2007, 16:06
- - Hexxx   А меня опять оказался баг с переключением DATA0/DA...   May 4 2007, 12:08
- - Hexxx   Начал пробовать подключать разные устройства. Кто-...   May 7 2007, 08:32
- - Hexxx   А вообще когда проставляется TIMEOUT?   May 7 2007, 13:49
- - Hexxx   ап   May 8 2007, 13:41
|- - Ailinor   Я решил так: int Read(unsigned char *buff) { ...   May 10 2007, 15:18
- - Hexxx   Я тут тоже по этому вопросу мучаю разных людей. Од...   May 11 2007, 13:17
- - Hexxx   Кое-что еще выяснилось на счет таймаутов. Если де...   May 17 2007, 05:05
- - Hexxx   А фишка оказалась была в том, что я не делал SetAd...   Jun 18 2007, 12:58


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

 


RSS Текстовая версия Сейчас: 25th July 2025 - 11:00
Рейтинг@Mail.ru


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