Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: CY7C68013A постоянная булочная передача
Форум разработчиков электроники ELECTRONIX.ru > Интерфейсы > Форумы по интерфейсам > RS232/LPT/USB/PCMCIA/FireWire
torik
Снова привет!

Ковыряюсь с этой платой CY3681, драйвер CyUSB....

Состряпал девайс - точка 1 IN интераптовая а также точки 2 OUT и 6 IN по 512 байт.
Пока зациклена точка 2 на точку 6, т.е. чо передаем с компа то обратно отсылаем...
Все это проверяется с помощью CyConsole... и вот какая проблема: в этой программе нельзя непрерывно принимать данные и записывать их в файл.

Может знает кто какую прогу чтобы это делать или другой выход? а то я с програмированием под комп на твою мать...
Warlord
Выход один, учиться программировать на ПК. Это тебе еще не раз пригодится. Такую прогу сделать - десяток строк набросать smile.gif
torik
Аха - все получилось. Принимаю данные.
Следующий шаг - настроить автоточку. Данные в нее гнать с фифо (видео) и на компе принимать
torik
Ну вот и снова я...

Первый вопрос (не принципиальный, т.к. могу обойтись), спрашиваю из интереса:
- почему когда 6 IN точку настраиваем как интерапт или булочную в дескрипторах, а после вручную заполняем, то передача идет нормально без ошибок. Но когда делаем точку изохронной - все время получаем "Isoc IN Transfer. Isoc IN failed"? Как-то по-другому надо изохронной точкой пользоваться? (просто запись счетчика EP6BCH(L) не катит)...


А второй вопрос заключается в следующем:
В моем девайсе сделана точка 86 - IN, Bulk, 512 байт, 4-ёх кратная буферизация. На входы FD0-FD7 (PORTB) контроллера подается параллельный код с цифровой ч/б камеры (каждый байт - пиксель, разрешение 640*480), строб с этой камеры идет на вход SLWR контроллера (передний фронт), FIFOADR1:0 соответственно заданы как 10. Задача - качать этот поток байтов в комп.

Настраиваю ФИФО и точку следущим образом:

Код
    CPUCS = ((CPUCS & ~bmCLKSPD) | bmCLKSPD1);
    SYNCDELAY;
    IFCONFIG |= 0x4B;                                        //SLAVE FIFO, àñèíõð.
    SYNCDELAY;

    REVCTL = 0x03; // must set REVCTL.0 and REVCTL.1 to 1
    SYNCDELAY;
    SYNCDELAY;

    EP1OUTCFG = 0x00;                                        //see TRM section 15.14
    EP1INCFG = 0xb0;
    SYNCDELAY;                                                //in
    EP2CFG = 0xA0;                                            //out 4
    SYNCDELAY;                    
    EP4CFG = 0x00;
    SYNCDELAY;                    
    EP6CFG = 0xE0;                                            //in 4
    SYNCDELAY;                    
    EP8CFG = 0x00;

    FIFORESET = 0x80; // reset all FIFOs
    SYNCDELAY;
    FIFORESET = 0x02; // reset EP2
    SYNCDELAY;
    FIFORESET = 0x04; // reset EP4
    SYNCDELAY;
    FIFORESET = 0x06; // reset EP6
    SYNCDELAY;
    FIFORESET = 0x08; // reset EP8
    SYNCDELAY;
    FIFORESET = 0x00;
    SYNCDELAY;

    EP2FIFOCFG = 0x0;                                        //ýòè òî÷êè áåç ôèôû
    SYNCDELAY;
    EP4FIFOCFG = 0x0;
    SYNCDELAY;
    EP8FIFOCFG = 0x0;
    SYNCDELAY;

    EP6FIFOCFG = 0x08;                                        //8, àôòàèí,
    SYNCDELAY;
    EP6AUTOINLENH = 0x02;                                    //512
    SYNCDELAY;
    EP6AUTOINLENL = 0x00;
    SYNCDELAY;

    SYNCDELAY;                    
    EP2BCL = 0x80;                // arm EP2OUT by writing byte count w/skip.
    SYNCDELAY;                    
    EP2BCL = 0x80;
    SYNCDELAY;                    
    EP2BCL = 0x80;                // arm EP2OUT by writing byte count w/skip.
    SYNCDELAY;                    
    EP2BCL = 0x80;
    SYNCDELAY;                    
    EP4BCL = 0x80;                // arm EP4OUT by writing byte count w/skip.
    SYNCDELAY;                    
    EP4BCL = 0x80;    
    SYNCDELAY;                    
    EP4BCL = 0x80;                // arm EP4OUT by writing byte count w/skip.
    SYNCDELAY;                    
    EP4BCL = 0x80;    

    // enable dual autopointer feature
    AUTOPTRSETUP |= 0x01;



Чо не так настраиваю? Все время сплошные 0xB5 передаются.
На компе накалякана прога (с примера bulkloop содрана и доделана) и все передачи в ней неправильные. Когда вручную заполняю точку - все работает.
Вообще настроил вроде по мануалу, подозреваю - может прога на компе не справляется с приемом данных?

Но даже если не справляется и перегруз буферов ФИФО идет, разве я не должен через CyConsole хотя бы первае 4 512-ибайтных пакета получить?
torik
ах да - может это както связано с регистром AUTOPTRSETUP?
jur
Цитата(torik @ Feb 6 2007, 08:56) *
ах да - может это както связано с регистром AUTOPTRSETUP?
Не думаю. AUTOPTR - вообще штука удобная, не нужно делать дополнительное приращение указателей адресов массивов. Хотя это и не принципиально...

Ты расписал инициализацию, но не показал, как сделана сама передача данных. Может там "собака порылась"?
torik
Дык а чего еще нужно? К ФИФО подключены данные, асинхронный режим - передним фронтом запись.
Разве контроллер по заполнении буфера не должен передавать автоматически?
jur
Цитата(torik @ Feb 7 2007, 13:55) *
Дык а чего еще нужно? К ФИФО подключены данные, асинхронный режим - передним фронтом запись.
Запись данных в микросхему происходит по заднему фронту, а не по переднему. Данные должны быть стабильны минимум за 10 ns перед ним и после него (документ "EZ-USB FX2LP USB Microcontroller", файл "cy7c68013a_8.pdf", стр. 46). Может в этом дело?

Еще полезно было бы сделать тестовый режим, когда данные приходят не от камеры, а генерятся самим микроконтроллером. Для проверки всего тракта от CY7C68013A до компьютерной программы.
torik
Цитата(jur @ Feb 7 2007, 17:05) *
Запись данных в микросхему происходит по заднему фронту, а не по переднему.
Данные должны быть стабильны минимум за 10 ns перед ним и после него (документ "EZ-USB FX2LP USB Microcontroller", файл "cy7c68013a_8.pdf", стр. 46). Может в этом дело?


EZ-USB FX2 CY7C68013 technical reference manual, страница 9-3, рис. 9-3. В асинхронном режиме запись/чтение происходит при переходе из активного в неактивный, по-умолчанию это 0 -> 1, т.е. передний фронт... Кроме того можно сделать и задний фронт... Учтено.

Цитата(jur @ Feb 7 2007, 17:05) *
Еще полезно было бы сделать тестовый режим, когда данные приходят не от камеры, а генерятся самим микроконтроллером. Для проверки всего тракта от CY7C68013A до компьютерной программы.


А ведь верно - это было бы удобно. Данные можно выдавать по PORTD (я использую 8 разрядов ФИФЫ), а куды лучше девать сигнал SLWR и флаги?

На фсякий случай выкладываю сам свой проект (там усе делается в файле bulkext.c
jur
Цитата(torik @ Feb 8 2007, 08:00) *
EZ-USB FX2 CY7C68013 technical reference manual, страница 9-3, рис. 9-3. В асинхронном режиме запись/чтение происходит при переходе из активного в неактивный, по-умолчанию это 0 -> 1, т.е. передний фронт... Кроме того можно сделать и задний фронт... Учтено.
Вот в чем дело! Я просто не понял, т.к. привык называть "передним фронтом" тот фронт, который приходит первым (вне зависимости от его полярности). В этом случае все правильно.

Цитата(torik @ Feb 8 2007, 08:00) *
А ведь верно - это было бы удобно. Данные можно выдавать по PORTD (я использую 8 разрядов ФИФЫ), а куды лучше девать сигнал SLWR и флаги?
Проще всего, IMHO, сделать так: заполняешь чем-нибудь буфер соответствующей ендпойнты и посылаешь его компьютеру. Т.е. вот такой код:

if(!(EP2468STAT & bmEP6FULL))
{ // check EP6 FULL(busy) bit in EP2468STAT (SFR), core set's this bit when FIFO is full
// Заполняешь буфер чем хочешь, например просто байтом счетчика пакетов
EP6FIFOBUF[0] = packet_counter++;
EP6BCH = 2; // send 512 bytes
SYNCDELAY;
EP6BCL = 0; // arm EP6IN
}

Цитата(torik @ Feb 8 2007, 08:00) *
На фсякий случай выкладываю сам свой проект (там усе делается в файле bulkext.c
Интересно будет ознакомиться. Завтра на работе посмотрю.
torik
Насчет проверки... Сделано, только программное заполнение буфера - пройденный этап.
Я сделал так:
- с порта D на порт B кинул провода - это типа данные на вход ФИФО smile.gif
- с порта C даю сигнал SLWR (в асинхронном режиме работаю)
- на порт С еще флаги принимаю и отображаю их на светодиоды.

Все работает, например, нажимаю кнопку и контроллер выдает на порты (на свои же) сигналы такие какие должны поступать с моей камеры. Смотрю флаги, принимаю пакеты на комп в консоль... и програмульку, сделанную на основе примера идущего в комплекте с CyAPI....
Но когда подключаю камеру все несколько сложнее - скорость порядка 11 Мбайт/с. И програмулька самодельная не справляется с приемом данных...
torik
Получилось - сигнал с камеры пошел... Только пришлось делать в синхронном режиме, чтобы всякий мусор не принимать...
Хм... теперь как бы все это забабахать на комп...
torik
Ладно, с железом разобрались... теперь с программой на компе:

если делаю запись принимаемых данных в файл - скорость 1 Мбайт/с
если запись в файл убрать - скорость 2 Мбайт/с

Как увеличить скорость? Она должна быть в районе 11 МБайт/с
jur
Цитата(torik @ Feb 12 2007, 08:44) *
Ладно, с железом разобрались... теперь с программой на компе:
если делаю запись принимаемых данных в файл - скорость 1 Мбайт/с
если запись в файл убрать - скорость 2 Мбайт/с
Как увеличить скорость? Она должна быть в районе 11 МБайт/с
Тут без вариантов. (Речь ведь идет о Винде, не так ли?) Нужно сделать отдельный поток, принимающий данные в ряд буферов. По мере их заполнения нужно в другом потоке производить блочную запись в файл. Причем, следует помнить о возможной ошибке: ни в коем случае не опрашивать готовность! Нужно пользоваться исключительно семафорами! Т.е. применить например такую пару (в потоке приема и потоке записи в файл соответственно):

SetEvent(DataBufferReadyEvent); -> WaitForMultipleObjects(2, m_hEventArray, FALSE, INFINITE);

Ну и, конечно, поиграться размерами и числом буферов, найти оптимум.
-Al-
Цитата(torik @ Feb 12 2007, 09:44) *
Ладно, с железом разобрались... теперь с программой на компе:

если делаю запись принимаемых данных в файл - скорость 1 Мбайт/с
если запись в файл убрать - скорость 2 Мбайт/с

Как увеличить скорость? Она должна быть в районе 11 МБайт/с

Странно вообще... даже в одном потоке можно добится 11МБ/сек, у Вас буфер передачи какой??
torik
Извиняюсь, три дня на работе без инета sad.gif
Посмотрел как сделано в примере "стример" что в комплекте с CyAPI.lib лежит... Сделал усе как там (и как вы говорите) - поток отдельный, очередь из четырех (вполне хватило)... Без проблем принимаю данные на скорости около 10 МБАйт/с, сколько камера и передает, пакеты не теряю (по флагам сморю).

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

Кто бы как сделал?
jur
Цитата(torik @ Feb 13 2007, 19:03) *
Теперь последняя проблема: на компе получаю картинку, но нет синхронизации...
Выход вижу такой - по кадровому импульсу контроллер заполняет еще одну точку булочную, а на компе когда дождался приема от этой точки - начинаю ждать приема строк....
Кто бы как сделал?
IMHO, проще всего в качестве самой первой точки строки передавать маркерный байт. Таким образом полезный кадр уменьшится на одну точку. Думаю, для видеокамеры это совершенно некритично. Таким образом, самая первая строка передается, например, с маркерным байтом 0xFF или 0x00, а последующие с каким-нибудь другим кодом. У меня так сделано в ультразвуковом сканере. Правда, у меня строк не более 192-х, поэтому я передаю маркерный байт 0xFF для особого М-луча, а для остальных - просто их номера. На приемной стороне я копирую вторую точку на место первой, чтобы число точек в луче осталось 512.
torik
ыхы - вот только маркерный байт не подет - остальные данные тоже могут быть любыми, т.е. за 300 кБайт кадра встретится не раз любое число...

Делаю так: кадровые положыельные синхроимпульсы подаю на ногу контроллера, например PA0 (а дальше даю маркерный пакет или по отдельной точке пакет). Уже становится лучше...
Но кадровый импульс в несколько раз короче чем основной цикл TD_Poll().
Хочу сделать прерываниями... Но как??!!!
Прерывание от INT0 (PA0) разрешить битами соответсвующими, а дальше чо?
У меня прога на СИ кейловском с их же примеров переделанная.
- вектор прерывания INT0 = 0х0003, но в таблице векторов (вроде USBJump.obj) по адресу 0 стоит команда LJamp из трех байт, а по адресу 4 еще один вектор, т.е. в таблицу не пихнуть

Как на СИ обработать это прерывание то?

И вдогонку - делать синхронизацию путем передачи по еще одной булочной точке пакета из нескольких байт - правильно ли?
jur
Цитата(torik @ Feb 14 2007, 18:19) *
ыхы - вот только маркерный байт не подет - остальные данные тоже могут быть любыми, т.е. за 300 кБайт кадра встретится не раз любое число...
Это не важно. Просто передаешь в каждом пакете только первый байт - маркерный и все. На стороне приемника не задумываясь смотришь на этот первый байт. Если 0xFF - то первая строка (начало кадра), если не 0xFF, то обычная следующая строка. При передаче, конечно, обеспечиваешь, чтобы первый байт был не байтом данных, а именно этим маркерным байтом (т.е. для начала кадра ставишь первый байт в 0xFF, а для всех последующих - в 0x00).
Цитата(torik @ Feb 14 2007, 18:19) *
И вдогонку - делать синхронизацию путем передачи по еще одной булочной точке пакета из нескольких байт - правильно ли?
Не думаю, что правильно. Дело в том, что если применяются две булочные ендпойнты, то нет гарантии, что они передадутся строго в нужном порядке, т.к. булочная передача в принципе не гарантирует время доставки пакета. Используй маркерный байт, не ошибешься :-) Ведь в этом случае ты гарантируешь, что каждый пакет содержит верную информацию о синхронизации (первая это строка, или не первая).
torik
О - спасибо - насчет маркерного байта понял. Тут правда все равно остается проблема - строка равна 640 байт, а PKTEND я не использую, т.е. почти в середине каждой строки будет еще один ненужный байт! (на крайняк придется использовать PKTEND)

Про вторую булочную тоже ясно...

И остался не решенным вопрос по прерываниям - нет ли какого-нибудь примера реализации прерывания INT0 на СИ?
jur
Цитата(torik @ Feb 15 2007, 10:44) *
И остался не решенным вопрос по прерываниям - нет ли какого-нибудь примера реализации прерывания INT0 на СИ?
Никаких проблем. Создаешь функцию, например, "INT0_isr" и назначаешь ей вектор прерывания INT0:

Код
BYTE InterruptCounter = 0;

void INT0_isr(void) interrupt INT0_VECT
{
   // Делаем что-нибудь в прерывании, например, приращаем некий счетчик
   InterruptCounter++;
}


Это порождает корректный машинный код:

Код
            ; FUNCTION INT0_isr (BEGIN)
                                          ; SOURCE LINE # 373
                                          ; SOURCE LINE # 375
0000 0500        R     INC     InterruptCounter
                                          ; SOURCE LINE # 376
0002 32                RETI    
            ; FUNCTION INT0_isr (END)


И все дела. Только нужно не забыть вставить эту функцию в тот файл, где нет прагмы:

#pragma NOIV // Do not generate interrupt vectors

Иначе вектор прерывания компилятором не будет сгенерирован.
jur
Цитата(torik @ Feb 15 2007, 10:44) *
Тут правда все равно остается проблема - строка равна 640 байт, а PKTEND я не использую, т.е. почти в середине каждой строки будет еще один ненужный байт! (на крайняк придется использовать PKTEND)
Кстати, вот эта твоя задача - еще один пример, когда размер ендпойнты желательно иметь больше 512 байт! Я с Сайпресом сейчас переписываюсь по этому поводу. После нескольких банальных ответов, они наконец поняли, что я так просто не отстану :-) Я добился у них информации, что на данной микросхеме можно получить скорость в 20-30 МБ/сек для Interrupt endpoint с размером пакета 1024 байта. Но примера реализации такого режима у них нема. Тогда после нескольких циклов обмена письмами я послал им свои пробные проекты (в CY7C68013A просто непрерывно генерятся пакеты, а на PC крутится приложение Streamer и подсчитывает скорость передачи этих пакетов). Вот уже 9 дней они молчат... Видать, озадачил я их :-) Когда получу ответ - сообщу в форуме, как обещал.
torik
насчет интераптовых "быстрых" точек - я читал твою тему, жду с нетерпением результатов.

Они там, наверное, действительно в шоке от русских умельцев smile.gif

Спасибо за пояснение про прерывания, щас буду пробывать, только бы он не испортил УСБшные прерывания...
torik
Тэкс, прерывания не спасли sad.gif
Возможно дело в программе на компутере... Попытаюсь описать проблему:

С камеры идут следущие сигналы:
- кадровые импульсы на вход INT0, прерывание срабатывает по фронту
- данные 8 разрядов идут на FIFO (PORTB, восьмиразрядный режым)
- на вход IFCLK идет тактовый сигнал с камеры (передним фронтом тактирует данные)
- на вход SLWR подаются строчные (ну почти, там еще гасящие учтены) импульсы, т.е. во время строки (640 байт) разрешается запись в ФИФО. Всего между кадровыми 480 строчных импульсов. Между задним фронтом кадрового импульса и первой строкой примерно 6500 тактов.
- еще адрес точки задается равным 10 на выводах FIFOADR0,1

Инициализация в сапрасовском МК следующая:
Код
void TD_Init(void) {
    PORTACFG = 1;        //PA0 будет входом прерывания от кадров

    PORTCCFG = 0;                //этот порт в принципе не используется
    OEC = 0x0b;                    //так только чтобы флаги выводить на светодиоды
    IOC = 0x0e;

    SYNCDELAY;
    CPUCS = 0x10;
    SYNCDELAY;
    IFCONFIG = 0xcb;         //при включении ФИФО внутреннее
                                               //тактирование, чтобы хрень не принимать
    SYNCDELAY;
    REVCTL = 0x03; // must set REVCTL.0 and REVCTL.1 to 1
    SYNCDELAY;
    SYNCDELAY;

    EP1OUTCFG = 0x00;     //нас будет интересовать только точка 6 в режыме IN
    EP1INCFG = 0xb0;
    SYNCDELAY;    
    EP2CFG = 0xA0;        
    SYNCDELAY;                    
    EP4CFG = 0x00;
    SYNCDELAY;                    
    EP6CFG = 0xE0;
    SYNCDELAY;                    
    EP8CFG = 0x00;
    SYNCDELAY;                    

    FIFOPINPOLAR = 0x04;       //для записи - активный высокий, т.к. такие уж строчные
    SYNCDELAY;

    for (i = 0; i < 4; i++) {       //хм... хватилобы и один разок
        FIFORESET = 0x80;  
        SYNCDELAY;
        FIFORESET = 0x02;  
        SYNCDELAY;
        FIFORESET = 0x04;    
        SYNCDELAY;
        FIFORESET = 0x06;    
        SYNCDELAY;
        FIFORESET = 0x08;    
        SYNCDELAY;
        FIFORESET = 0x00;
        SYNCDELAY;
    }

    EP2FIFOCFG = 0x0;                        //эти точки нафиг пока не нужны
    SYNCDELAY;
    EP4FIFOCFG = 0x0;
    SYNCDELAY;
    EP8FIFOCFG = 0x0;
    SYNCDELAY;

    EP6FIFOCFG = 0x04;                      //8 разрядов, пока не автаин, чтоб не леза дрянь
    SYNCDELAY;
    EP6AUTOINLENH = 0x02;               //пакеты по 512
    SYNCDELAY;
    EP6AUTOINLENL = 0x00;
    SYNCDELAY;

    OED = 0xff;
    IOD = 0xff;

    Rwuen = TRUE;                 // Enable remote-wakeup
}


Т.е. при включении хоть с камеры уже и идут данные, но мы их не принимаем, отключив внешние такты на ФИФО и точку сделав ручной.

По прерываниям от кадрового импульса:

Код
void INT0_isr(void) interrupt INT0_VECT
{
    PC0 = PC0 ^ 1;              //это я так сморю нет ли пропусков кадровых импульсов (нету...)

    if (nachalo == 1) {         //флаг nachalo выставляется при нажатии кнопки, а сбрасывается при
                                            //приходе следующего кадрового импульса
        SYNCDELAY;  
        FIFORESET = 0x80;  //очистить ФИФО
        SYNCDELAY;
        FIFORESET = 0x06;
        SYNCDELAY;
        FIFORESET = 0x00;
        SYNCDELAY;

        IFCONFIG = 0x03;   //вот тут делаем внешние такты (от камеры) и синхронный режим
        SYNCDELAY;

        EP6FIFOCFG = 0x0c;  //вот теперь точка стала автаин... пошел прием даных
        SYNCDELAY;
        EP6AUTOINLENH = 0x02;
        SYNCDELAY;
        EP6AUTOINLENL = 0x00;
        SYNCDELAY;

        nachalo = 0;
    } else {                                              //в следующем же кадре хватит принимать
                                                                 //чтобы у нас только один кадр был
        IFCONFIG = 0xcb;                      //нафиг внешние такты
        SYNCDELAY;

        EP6FIFOCFG = 0x04;               //на всякий случай точку в ручной режим
        SYNCDELAY;
        EP6AUTOINLENH = 0x02;
        SYNCDELAY;
        EP6AUTOINLENL = 0x00;
        SYNCDELAY;

        SYNCDELAY;  
        FIFORESET = 0x80;
        SYNCDELAY;
        FIFORESET = 0x06;
        SYNCDELAY;
        FIFORESET = 0x00;
        SYNCDELAY;
    }
}


Вот, т.е. нажали кнопку установив при этом флаг nachalo, и при приходе кадрового импульса разрешаем передачу данных в течении одного кадра. это 640*480 байт или 600 пакетов по 512 байт.

Значицца, как же это принимаю на компе? А вот так (делаю не я, а програмист на компе, лучшеб конечно он объяснил ну да лана):
Код
    dlg->CtrlEndPt->TimeOut = 1500;
    dlg->InEndPt->TimeOut = 1500;
    dlg->InEndPt->XferData(buffers[0], len); //вот собственно :)


Делали и очередь по приему, как это написано в примере "Стриммер". Вывод на экран правильный, пробовал заменять принятый буфер buffers[0] на чото свое - все норм.

И проблема осталась прежней sad.gif
- картинка разбита на куски. Нет синхронизации ни строчной походу ни кадровой (т.к. разбивается и по вертикали и по горизонтали).

Нажимаем кнопку "прием" и сразу же на плате кнопку, которая ставит флаг nachalo... и - пакет принимается не полностью, вроде не сначала. причом что интересно в разбиении картинки имеется повторяемость - примерно каждые 100 пикселей по вертикали разбиватет. Т.е. картинка состоит из 4,8 полосок по вертикали и по горизонтали похоже на то же самое.

Что тут может быть не так? Прога для компа или для МК, как отличить???
jur
Тяжело вот так, дистанционно, понять проблему... Думаю, что стоило бы разбить сложную задачу на более простые части. Например, нет-ли возможности организовать запись с камеры только 512 байт, а оставшуюся часть строки просто отбрасывать? Это позволило бы проверить и отладить синхронизацию. На этапе отладки, думаю, можно мириться с тем, что остаток кадра не виден. Т.е. организовать такой автомат, который пишет строку (указывая в первом байте маркер начала кадра) только до 512-го байта, а остаток отбрасывает. В этом случае можно было бы отработать все моменты системы. А потом, когда все заработает, продумать расширение строки до полных 640 пикселей.
torik
хм...
Оказывается комп пропускает пакеты иногда, примерно 1-2 пакета на каждые 64 кБайт приема....

Как сделать на основе стримера высокий приоритет потоку?
-Al-
@torik
Я тут чего-то не понял?? Вы пытаетесь с помощью микроконтроллера поймать начало кадра и засинхронизировать данные в FIFO???? Если так, то напрасно Вы это затеяли, скорости микроконтроллера НИКОГДА не хватит для этой задачи, тут если только в железе делать, на ПЛИС например... Тем более у Вас в обработчике прерываний SYNDELAY и сбросы FIFO, вообще непонятно, что Вы тогда принимаете, на эти процедуры уходит уйма времени.... Дейстивтельно, поставьте ПЛИС мжеду камерой и FIFO FX2, в ней и сделаете всё что надо smile.gif
torik
А с помощью чего еще ловить начало кадра?
По прерыванию от кадрового импульса сбрасываю ФИФО, как без этого...

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

А насчет того что не успевает - у меня же 6500 тактов камеры имеется в распоряжении... А ПЛИСа нету у меня, да и больно дорого станет.
jur
Цитата(torik @ Feb 16 2007, 14:05) *
Как сделать на основе стримера высокий приоритет потоку?
Это очень несложно. Вот как поступаю я:

Код
  XferThread = CreateThread(NULL,0,XferLoop,0,CREATE_SUSPENDED,(LPDWORD )&lpThreadId);
  if(XferThread == NULL) {
    return false;
  }
  if(SetThreadPriority(XferThread,THREAD_PRIORITY_TIME_CRITICAL) == 0) {
    CloseHandle(XferThread);
    return false;
  }
  if(ResumeThread(XferThread) == -1) {
    CloseHandle(XferThread);
    return false;
  }
  return true;

При этом я четко заметил, что флаг THREAD_PRIORITY_TIME_CRITICAL полностью решает проблему с пропаданием пакетов. Правда, зависит от всего остального. Если на компьютере выполняются другие важные задачи, то пакеты могут пропадать... Тогда нужно принимать более радикальные меры.
-Al-
Цитата(torik @ Feb 16 2007, 17:26) *
А с помощью чего еще ловить начало кадра?
По прерыванию от кадрового импульса сбрасываю ФИФО, как без этого...

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

А насчет того что не успевает - у меня же 6500 тактов камеры имеется в распоряжении... А ПЛИСа нету у меня, да и больно дорого станет.

Во первых - абсолютно некорректно в обработчике прерывания трогать какие-либо регистры контроллера и, тем более, вводить такты ожидания (SYNCDELAY)! Там должно быть ТОЛЬКО изменения какого-либо флага, по которому в основном цикле уже надо начинать обработку.
Во вторых - насколько помню, после сброса FIFO в FX2, надо выждать порядка 100мкс, прежде чем начинать писать туда что либо.
В третьих - начало кадра лучше ловить с помощью ПЛИС да и проблема с пакетами исчазла бы сама собой, писали-бы всё в навал...
Кстати, для передачи такого потока информации в реальном времени через Bulk EP без внешнего буфера не обойтись, иначе будут потери, внутреннего буфера FX2 просто будет недостаточно, так-что Вам, для нормальной работы Вашего устройства просто необходимо ставить ПЛИС.

И что это за 6500 тактов камеры???

Цитата(jur @ Feb 16 2007, 18:56) *
Цитата(torik @ Feb 16 2007, 14:05) *
Как сделать на основе стримера высокий приоритет потоку?
Это очень несложно. Вот как поступаю я:

Код
  XferThread = CreateThread(NULL,0,XferLoop,0,CREATE_SUSPENDED,(LPDWORD )&lpThreadId);
  if(XferThread == NULL) {
    return false;
  }
  if(SetThreadPriority(XferThread,THREAD_PRIORITY_TIME_CRITICAL) == 0) {
    CloseHandle(XferThread);
    return false;
  }
  if(ResumeThread(XferThread) == -1) {
    CloseHandle(XferThread);
    return false;
  }
  return true;

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

Это имеет смысл только на скоростях близких к масимуму (~40МБ/сек) при меньших скоростях, тем более при скорости 10МБ/сек делать такое для того, чтобы не терялись пакеты - просто шаманство smile.gif Если пакеты теряются - надо перерабатывать аппаратную часть, вводить дополнительный буфер.
jur
Цитата(-Al- @ Feb 16 2007, 18:06) *
Это имеет смысл только на скоростях близких к масимуму (~40МБ/сек) при меньших скоростях, тем более при скорости 10МБ/сек делать такое для того, чтобы не терялись пакеты - просто шаманство smile.gif Если пакеты теряются - надо перерабатывать аппаратную часть, вводить дополнительный буфер.
С одной стороны - это так, а с другой стороны, применил флаг THREAD_PRIORITY_TIME_CRITICAL и все! Ни тебе перерабатывать аппаратную часть надо, ни вводить дополнительный буфер. Дешево и сердито :-)
torik
AL, "6500 тактов камеры" - это значит чуть более 10 строк (т.е. почти 500 мкс)...
Спасибо, учту замечания по поводу прерываний (хотя я не вкуриваю, почему нельзя в прерывании заполнить к примеру буфер точки 1 in)...

А ПЛИС - ну и что если ее постаить - синхронизация то все равно должна быть!!!! Комп как-то должен узнать о начале кадра.
-Al-
Цитата(jur @ Feb 17 2007, 12:38) *
С одной стороны - это так, а с другой стороны, применил флаг THREAD_PRIORITY_TIME_CRITICAL и все! Ни тебе перерабатывать аппаратную часть надо, ни вводить дополнительный буфер. Дешево и сердито :-)

Вы никогда не задумывались над тем, что в системе могут быть другие устройства, не менее требовательные к ресурсам, и что тогда????

Цитата(torik @ Feb 17 2007, 13:38) *
AL, "6500 тактов камеры" - это значит чуть более 10 строк (т.е. почти 500 мкс)...
Спасибо, учту замечания по поводу прерываний (хотя я не вкуриваю, почему нельзя в прерывании заполнить к примеру буфер точки 1 in)...

А ПЛИС - ну и что если ее постаить - синхронизация то все равно должна быть!!!! Комп как-то должен узнать о начале кадра.

Насчет обработчика прерываний... не забывайте, во время выполнения прерывания Вы монопилизируете ресурсы контроллера, тем самым рискуете потерять другие прерывания.
На ПЛИС достаточно просто вставить в поток от камеры маркерное слово, которое и будет означать начало кадра/строки wink.gif
torik
Аха, понял про прерывания, это учитываю.

Что касается ПЛИС - это будет следующий шаг, т.к. их только еще осваивать буду smile.gif

Почему цепляюсь просто за камеру+сайпрас, хм... видел готовый продукт sad.gif... Очень привлекательно то что это всего лишь дешевая цифровая камера и махонький контроллер, очень получается все дешево и хорошо...

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

Второй вариант (не знаю почему он мне не нравится) - буду вместо второй точки просто пихать между кадрами маркерный пакет.

И кстати, попробовал сделать точку размером 640 байт (как строка) - чото нифига не хочет комп с ней работать, а когда через консоль смотрю - последние (640-512) байт забиваются какойто лажей...
jur
Цитата(-Al- @ Feb 17 2007, 14:00) *
Вы никогда не задумывались над тем, что в системе могут быть другие устройства, не менее требовательные к ресурсам, и что тогда????
А тогда - в точности то, о чем я и написал: "Правда, зависит от всего остального. Если на компьютере выполняются другие важные задачи, то пакеты могут пропадать..." :-) Т.е. зависит от задачи. От этой печки и следует плясать. Очень может быть, что других высокоприоритетных задач в это время выполняться не будет.
Цитата(torik @ Feb 17 2007, 14:42) *
И кстати, попробовал сделать точку размером 640 байт (как строка) - чото нифига не хочет комп с ней работать, а когда через консоль смотрю - последние (640-512) байт забиваются какойто лажей...
А он и не может работать с ендпойнтой размером 640 байт, IMHO. Из этого диапазона только 512 или 1024.

Кстати. А ведь можно передавать одну порцию (начальную часть строки) размером 512 байт, а остаток - сколько получится (используя PKTEND). Тогда можно и маркерный байт без труда добавить (да хоть даже слово: например номер строки в диапазоне 0...639), т.к. места - 2 х 512 байт - предостаточно. А программист всегда сможет определить начало строки по полученной величине пакета ровно 512 байт. Или добавить номер строки в конец (т.е. во второй, укороченный пакет). Тогда на передающей стороне проще получится, а на компьютерной стороне - вообще пофиг. Стоит подумать, IMHO. Тогда задача решается вообще элементарно. И не нужно никаких ПЛИСов и прочей усложненности городить.
torik
А как контроллер будет определять что PCKTEND получен, успеет он?
И кстати тоды по пктенду записать один байт в точку а остальные 640 допишутся...
torik
Короче, вот такой будет вопрос...

Кадр = 640*480, енто мы принимаем по булочной In точке в виде 5-и буферов по 120*512 байт (т.е. = 640*480 = 512*600). Это все в одном потоке с высоким приоритетом. Как приняли эти 640*480 байт, передаем их в ф-ю вывода на экран.
в параллельном потоке принимаем по второй булочной In точке 3 байта, которые сайпрас передает каждый кадр (1/30 сек)

Иногда во время приема почему-то (дело вроде не в железе) пропадают пара-тройка пакетов по 512 байт. Но вот тут-то
Код
if (dlg->InEndPt->FinishDataXfer(buffers[i], rLen, &inOvLap[i], contexts[i], isoPktInfos[i])) {
.......


ждет себе заполнения буфера до размера 640*480! А берет он их ясен пень из следующего кадра и, получаем сбой синхронизации.
Т.е. после запуска программы пару секунд фсе нормуль, а потом сбой, еще через 1-2 сек опять и т.д. иногда даже раз в 0.5 сек (примерно)

Чтобы синхронизироваться надо бы при приеме кадровой синхронизации (иными словами по приему от второй In точки) делать как-то так чтобы буфер поновой заполнялся!!


КАК??
torik
Во блин дела... Тока заметили - пакеты 512 байт мы теряем не в железе. Я это по флагу переполнения смотрю (он не устанавливается)!
Пакеты теряем в компе. Щас выбросили с проги все лишнее - стал терять 1-2 пакета в начале (или конце фиг пойму) кадра. Уже стало лучше.

Причем теряет не целиком пакет 512 байт! А лишь кусочек :0

Подскажите, где тут может быть собака зарыта?
jur
Цитата(torik @ Feb 19 2007, 09:12) *
А как контроллер будет определять что PCKTEND получен, успеет он?
Посчитать надо. Во всяком случае, микроконтроллер - штука достаточно быстрая, импульс длительностью порядка десятка/двух микросекунд должен увидеть лёгко.

Цитата(torik @ Feb 19 2007, 15:20) *
Иногда во время приема почему-то (дело вроде не в железе) пропадают пара-тройка пакетов по 512 байт. Но вот тут-то
Код
if (dlg->InEndPt->FinishDataXfer(buffers[i], rLen, &inOvLap[i], contexts[i], isoPktInfos[i])) {
.......

ждет себе заполнения буфера до размера 640*480! А берет он их ясен пень из следующего кадра и, получаем сбой синхронизации.
Конечно. Все дело в негарантированности доставки булочных пакетов. IMHO, тут единственная надежда - запуливать в очередь прием только двух пакетов и не больше (т.е. одной полной TV строки: 512+128 байт). А число очередей взять по-больше (8-16 штук). Но все равно, я не очень представляю, как без маркерного байта полностью избавиться от сбоев синхронизации...

Цитата(torik @ Feb 19 2007, 15:20) *
Чтобы синхронизироваться надо бы при приеме кадровой синхронизации (иными словами по приему от второй In точки) делать как-то так чтобы буфер поновой заполнялся!!
КАК??
Вот как раз при организации приема в 2 пакета на буфер (первый пакет полный, а второй - короткий, на 128 байт) и получится, что приход кадровой синхронизации тут же будет означать, что следующая строка - первая. Правда, может получиться, что синхроимпульс придет на текущую строку...

Кстати, тут может выручить тот факт, что временной промежуток для кадрового синхроимпульса заметно дольше (несколько строк). За счет этого можно как-то поиграться с синхронизацией... Думаю, стоит обдумать этот момент. Можно, к примеру, очень точно измерять время прихода строк и когда очередная строка придет сильно позже обычных - это и будет сигналом начала кадра. Тогда даже кадровая синхронизация через другую булку будет не нужна! :-)
torik
Цитата(jur @ Feb 19 2007, 18:44) *
Цитата(torik @ Feb 19 2007, 09:12) *
А как контроллер будет определять что PCKTEND получен, успеет он?
Посчитать надо. Во всяком случае, микроконтроллер - штука достаточно быстрая, импульс длительностью порядка десятка/двух микросекунд должен увидеть лёгко.

Чатота тактов с камеры почти 10 Мгц - о счете речи быть не может
Цитата
Цитата(torik @ Feb 19 2007, 15:20) *
Иногда во время приема почему-то (дело вроде не в железе) пропадают пара-тройка пакетов по 512 байт. Но вот тут-то
Код
if (dlg->InEndPt->FinishDataXfer(buffers[i], rLen, &inOvLap[i], contexts[i], isoPktInfos[i])) {
.......

ждет себе заполнения буфера до размера 640*480! А берет он их ясен пень из следующего кадра и, получаем сбой синхронизации.

Конечно. Все дело в негарантированности доставки булочных пакетов. IMHO, тут единственная надежда - запуливать в очередь прием только двух пакетов и не больше (т.е. одной полной TV строки: 512+128 байт). А число очередей взять по-больше (8-16 штук). Но все равно, я не очень представляю, как без маркерного байта полностью избавиться от сбоев синхронизации...

Булочные пакеты, путаем с изохронными - доставка гарантирована, кроме того я потом же выяснил - на железе не пропадают данные
Цитата
Цитата(torik @ Feb 19 2007, 15:20) *
Чтобы синхронизироваться надо бы при приеме кадровой синхронизации (иными словами по приему от второй In точки) делать как-то так чтобы буфер поновой заполнялся!!
КАК??
Вот как раз при организации приема в 2 пакета на буфер (первый пакет полный, а второй - короткий, на 128 байт) и получится, что приход кадровой синхронизации тут же будет означать, что следующая строка - первая. Правда, может получиться, что синхроимпульс придет на текущую строку...

Если ща у меня 5 раз принимается 120*512, то принимать скажем так 480 раз 512+128 не рулит, не принимает комп
Цитата
Кстати, тут может выручить тот факт, что временной промежуток для кадрового синхроимпульса заметно дольше (несколько строк). За счет этого можно как-то поиграться с синхронизацией... Думаю, стоит обдумать этот момент. Можно, к примеру, очень точно измерять время прихода строк и когда очередная строка придет сильно позже обычных - это и будет сигналом начала кадра. Тогда даже кадровая синхронизация через другую булку будет не нужна! :-)

хм... я глядел - наложения кадровой синхронизации (данных по второй токе) на строчные данные НЕТ. Просто когда мы ловим этот кадр - не понятно (да и можно ли), как начать прием совсем сначал. Разве что сделать Abort() и далее BeginXferData? корректро ли это....



Вот так, думается мне что проблема в правильности, грамотности написания кода на СИ. Делали переписывание полученных данных тупо циклом for, указатель=указатель. Были сбои в конце каждого из 5-и пакетов, когда заменили на memcpy - эти сбои почти ушли. Теперь стабильно теряется около 128 байт в последнем из пяти пакетов...
jur
Цитата(torik @ Feb 19 2007, 20:25) *
Чатота тактов с камеры почти 10 Мгц - о счете речи быть не может
Это не важно. Важно то, что кадровая синхронизация происходит достаточно медленно. Скажи, какая длительность кадрового синхроимпульса? Может быть его все-таки можно зафиксировать?

И еще. Почему нельзя синхронизироваться по периоду следования строк? В твоей системе нет временного промежутка для кадрового синхроимпульса? (Ведь в случае временной синхронизации отпадают проблемы с кадровым синхроимпульсом!)

Цитата(torik @ Feb 19 2007, 20:25) *
Булочные пакеты, путаем с изохронными - доставка гарантирована, кроме того я потом же выяснил - на железе не пропадают данные
Ты не понял, в булке гарантируется доставка пакетов, но не время их доставки! Тут запросто может возникнуть рассинхронизация... (Насколько я понял, именно рассинхронизация и имеет место быть.) А почему пропадают пакеты - Бог весть... Может программисты чего-то не того замутили?...

Цитата(torik @ Feb 19 2007, 20:25) *
Если ща у меня 5 раз принимается 120*512, то принимать скажем так 480 раз 512+128 не рулит, не принимает комп
Странно... Вот этого момента я не пойму...

Цитата(torik @ Feb 19 2007, 20:25) *
хм... я глядел - наложения кадровой синхронизации (данных по второй токе) на строчные данные НЕТ. Просто когда мы ловим этот кадр - не понятно (да и можно ли), как начать прием совсем сначал. Разве что сделать Abort() и далее BeginXferData? корректро ли это....
Можно. Аборта не надо, попробуй просто принимать по одному пакету в буфере. Это вызовет повышенный расход процессорного ресурса, но пока на это можно наплевать: главное понять, что не так работает. А оптимизировать можно потом.

Цитата(torik @ Feb 19 2007, 20:25) *
Вот так, думается мне что проблема в правильности, грамотности написания кода на СИ. Делали переписывание полученных данных тупо циклом for, указатель=указатель. Были сбои в конце каждого из 5-и пакетов, когда заменили на memcpy - эти сбои почти ушли. Теперь стабильно теряется около 128 байт в последнем из пяти пакетов...
Тоже верно... Тут запросто могут быть подводные камни... Думаю, следовало бы промерить точный тайминг. Пошагово. Это часто помогает.

(Прошу прощения, что мои советы выглядят как-то нелепо. Просто дистанционно понять проблему достаточно трудно :-)
Warlord
Интересно получается, пакеты пропадают. Для начала необходимо разобраться именно с этим, а потом уже с синхрой. Я генерил плисой поток, счетчик 16бит, и гнал на комп булочной передачей. А на компе проверял этот счетчик. Так вот, при скорости порядка 37МБ/с за 5 минут тестирования счетчик ни разу не сбился т.е. небыло ни одного потерянного пакета. Булочная - пакет гарантировано будет доставлен драйверу. Если драйвер попросит у железки 600 пакетов по 512 байт, и выделит достаточно места, то железо передаст именно 600 пакетов, а не больше и не меньше. Дальше уже дело аппликухи достать эти данные и обработать. Вполне вероятно вы просто не успеваете это делать, или делаете некорректно, особенно если учесть что используется больше одной очереди. Насчет синхронизации, использовать вторую булочную - не есть правильно. Частота 1/30 - 33мс период. Windows не ОСРВ, ее квант как раз и примерно 30 мс, и никто не гарантирут, что эту саму синхру вы будете получать каждые 33мс. Поэтому так поступать просто нельзя. Очень хороший вариант был уже озвучен - это маркер-пакет, пакет с известным "уникальным" содержимым или уникальной длины (pkend тоже хорошая штука). Если хотите получать "чистую" картинку, то между камерой и мк, просто необходимо ставить плису, она займется и синхронизацией, и забивкой фифо и всеми остальными делами.
torik
Потерю пакетов устранили! Картинка получилась, за несколько минут сбоев не происходит...

Теперь думаю над кадровой синхронизацией, ведь если все же за длительное время работы произойдет сбой, к примеру железа, происходит однократный сбой синхронизации и картинка становится разбитой на 4 части. Это я проверял искуственно создавая сбой... Этот случай надо предусмотреть.
Но, если я буду посылать компу, к приму в начале кадра "уникальный" пакет на 512 байт, то что с ним будут делать на компе-то? Чо весь буфер сканить на соответсвие, это же долго?
Warlord
Цитата
Как приняли эти 640*480 байт, передаем их в ф-ю вывода на экран.

Т.е. из драйвера прямиком на вывод, полагая, что первый байт буфера есть первая (верхняя левая) точка. Если сбоев нету, то все нормально, буфер размером 640*480=307200 байт содержит один кадр. Но если произойдет сбой, то как пример, первая точка может начаться где угодно, быть хоть первым байтом последней пачки(512 байт). Поэтому, для восстановления синхры, надо эту точку найти, можно, например, увеличить буфер на 512 байт (307712) и в первой пачке передавать какую-нить комбинацию, например первый, семнадцатый, 137 и 471 байты сделать известными. Тогда после приема 512+600*512 байт, надо глянуть в первые 512, найти все 4 байта, сделать вывод о наличии синхры. На это потребуется с десяток команд ПК. Если синхра потеряна, то просмотреть ВСЕ пачки по 512 байт и найти нужную. На это потребуется в худшем случае порядка 3000 тактов что на 600Мц ПК составит всего 5мкс, при периоде в 33мс.
torik
Хы... тоже верно, спасибо.

Но я всетаки сделал как и говорил - прием данных 640*480, после чего вывод их на экран, а затем ожидание приема от второй булочной точки. Далее цикл повторяется.

Получаем стабильную картинку, а в случае сбоя синхронизация востанавливается за 1 кадр!
Глюков пока не выявлено.
На Пне 3 ГГц, работа с полученным девайсом жрет менее 4% ресурса.

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