Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Не получается поймать глюк в CDC на AT90USB162
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
QuickWitted
В свое время я разрабатывал бесплатный для повторения проект по управлению компьютером с ПДУ на AT90USB162.

Смысл проекта был в том, что бы поднять CDC и через него обработанные передавать данные на компьютер.
но так как код проекта был очень большой, то пришлось писать его на ассемблере (вариант брать процессор
с большим ОЗУ я тогда не рассматривал).

Данных было мало, все бегало шустро (для ИК больше и не надо).

Единственный найденный тогда глюк заключался в том, что выяснилось -
получившийся исходник не работает на прием в потоковом режиме.
Передача шла нормально пакетами, но прием работал только в байтовом режиме.

К тому же оказалось что большинство программ для Windows (включая ГиперТерминал)
передают данные в RS232 побайтово (и глюк практически не проявлялся).

Сейчас пользователи попросили приделать к существующему приемнику мигалку, аналог Эмбилайт'а.
Мигалку я приделал, и возникла необходимость в потоковой загрузке данных в процессор...

стандартная функция чтения буфера выглядит так

Код
char uart_usb_getchar(void)
{
  register Uchar data_rx;
  Usb_select_endpoint(RX_EP);
  if (!rx_counter) while (!uart_usb_test_hit());
  data_rx=Usb_read_byte();
  rx_counter--;
  if (!rx_counter) Usb_ack_receive_out();
  return data_rx;
}


глюк заключается в том что функция data_rx=Usb_read_byte();
(на асме - lds R20_Arg1, UEDATX)

по непонятным мне причинам постоянно читает только первый байт буфера и не инкрементируется.

пример
;0x20,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09 отправляю
;0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20 приходит

Ну и собственно вопрос - Не подскажет ли доброуважаемый АЛЛ куда копать?

Долго копался сам, единственное что нашел:
в более свежих версиях исходника в эту функцию добавили еще одну строку
причем Usb_reset_endpoint_fifo_access вызывается везде перед чтением или записью...
но свежий исходник намного более сложен и я в нем к сожалению заблудился...
и не понятно нужна ли она для 162...

Код
char uart_usb_getchar(void)
{
  register char data_rx;

  if (!rx_counter) {
     while (!uart_usb_test_hit());
     [color="#FF0000"]Usb_reset_endpoint_fifo_access(RX_EP);[/color]
  }
  data_rx=Usb_read_endpoint_data(RX_EP, 8);
  rx_counter--;
  if (!rx_counter) Usb_ack_out_received_free(RX_EP);
        
  return data_rx;
}
Дэм
Дополню.

Данные со стороны компа передаются этой функцией
Цитата
BOOL TransmitCommChar(HANDLE hFile, char cChar);

Данная функция передает один (и только один) внеочередной байт в линию, не смотря на наличие данных в очереди передатчика, и перед этими данными. Однако управление потоком действует. Функцию можно вызвать только синхронно. Более того, если байт экстренных данных, от предыдущего вызова этой функции, еще не передан в линию (например из-за функций управления потоком), то попытка экстренной передачи еще одного байта завершится ошибкой.


Если же передать данные через WriteFile() допустим 2 байта и более, то на стороне микроконтроллера в буффере последний байт. Значит данные в FIFO, и программа в микроконтроллере забирает последний байт. Нужно узнать как из FIFO забрать все байты.
QuickWitted
Цитата(Дэм @ Mar 1 2012, 11:55) *
Если же передать данные через WriteFile() допустим 2 байта и более, то на стороне микроконтроллера в буффере последний байт. Значит данные в FIFO, и программа в микроконтроллере забирает последний байт. Нужно узнать как из FIFO забрать все байты.


Представлю - Дэм разработчик плагина, QuickWitted (т.е. я) разработчик прошивки.

Что байты уходят видно по логеру. А по rx_counter видно, сколько их пришло уже со стороны процессора...
т.е. я со стороны прошивки вижу прибыло скажем 10 байт. Но при чтении читаю почему то только первый.

На этой же системе передачи идут команды в нулевом ендпоинте...
и там все окей (раз устройство вообще определилось) и при таком же чтении в нулевом ендпоинте указатель инкрементируется, а тут нет.

Т.е. подряд и без какого либо дополнительного инкремента

Код
    lds    R16_Tmp1, UEDATX
    sts    ReqType, R16_Tmp1    ; 1
    lds    R17_Tmp2, UEDATX
    sts    bRequest, R17_Tmp2    ; 2
    lds    R16_Tmp1, UEDATX
    sts    wValueL, R16_Tmp1    ; 3 string_type
    lds    R16_Tmp1, UEDATX
    sts    wValueH, R16_Tmp1    ; 4 descriptor_type
    lds    R16_Tmp1, UEDATX
    sts    wIndexL, R16_Tmp1    ; 5
    lds    R16_Tmp1, UEDATX
    sts    wIndexH, R16_Tmp1    ; 6
    lds    R16_Tmp1, UEDATX
    sts    wLengthL, R16_Tmp1    ; 7
    lds    R16_Tmp1, UEDATX
    sts    wLengthH, R16_Tmp1    ; 8

ILYAUL
Цитата(QuickWitted @ Mar 1 2012, 11:48) *
Представлю - Дэм разработчик плагина, QuickWitted (т.е. я) разработчик прошивки.

Что байты уходят видно по логеру. А по rx_counter видно, сколько их пришло уже со стороны процессора...
т.е. я со стороны прошивки вижу прибыло скажем 10 байт. Но при чтении читаю почему то только первый.

На этой же системе передачи идут команды в нулевом ендпоинте...
и там все окей (раз устройство вообще определилось) и при таком же чтении в нулевом ендпоинте указатель инкрементируется, а тут нет.

Т.е. подряд и без какого либо дополнительного инкремента

Код
    lds    R16_Tmp1, UEDATX
     sts    ReqType, R16_Tmp1   ; 1
     lds    R17_Tmp2, UEDATX
     sts    bRequest, R17_Tmp2   ; 2
     lds    R16_Tmp1, UEDATX
     sts    wValueL, R16_Tmp1   ; 3 string_type
     lds    R16_Tmp1, UEDATX
     sts    wValueH, R16_Tmp1   ; 4 descriptor_type
     lds    R16_Tmp1, UEDATX
     sts    wIndexL, R16_Tmp1   ; 5
     lds    R16_Tmp1, UEDATX
     sts    wIndexH, R16_Tmp1   ; 6
     lds    R16_Tmp1, UEDATX
     sts    wLengthL, R16_Tmp1   ; 7
     lds    R16_Tmp1, UEDATX
     sts    wLengthH, R16_Tmp1   ; 8


Команда LDS , STS - это прямое обращение к данным в SRAM ( без инкремента или декремента) . Строго к определённой ячейке памяти И я не уверен , что в wLengthH , wIndexL и т.д. не записано одно и тоже число.

На asm чтение из буфера выглядит так

Код
ldi  count,10
Ldi ZH,HIGH(UEDATX)
Ldi ZL,LOW(UEDATX)

CYCLE:

LD  R20_Arg1,Z+  
st (или уже sts - если адрес приёмника не меняется) - кудато,R20_Arg1
dec count
brne CYCLE
QuickWitted
Цитата(ILYAUL @ Mar 1 2012, 13:57) *
Команда LDS , STS - это прямое обращение к данным в SRAM ( без инкремента или декремента) . Строго к определённой ячейке памяти И я не уверен , что в wLengthH , wIndexL и т.д. не записано одно и тоже число.


А я уверен, что разные...
Т.к. UEDATX не переменная.
и должна инкрементироваться автоматом, на аппаратном уровне...

в том куске кода все эти данные получаются правильно, т.к. без них (точнее, если хоть одна из них будет не та)
не произойдет определение USB устройства в виндовсе...

А девайс опознается и без глюков в определении (по схеме и с прошивкой из первого поста темы)
уже год работает более чем у 200 пользователей на разных машинах...

вопрос в другом - а почему UEDATX иногда не икрементится?

QuickWitted
Цитата(QuickWitted @ Mar 1 2012, 14:26) *
вопрос в другом - а почему UEDATX иногда не икрементится?


После поста тут, мне в ICQ форумчане посоветовали проверить RXOUTI
да действительно, пропадало, нашел куда, прописал доп условие... rolleyes.gif

всем спасибо за участие (как доделаем мигалку по типу эмбилайт – отпишусь о результатах).
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.