Gradient 1 22 февраля, 2010 Опубликовано 22 февраля, 2010 · Жалоба Собственно трудность заключается в медленном поднятии флага при вызове функции SignalISR(). Разместил флаги в секции "l2_var", функцию SignalISR() в секции "drivers_L1_code" Но это не помогло решить проблему. Принимаются блок данных по SPI, после корректного приёма заголовка должен устанвливаться флаг события. Если в коде обработчика прерывания от SPI по совпадению условий вызывается SignalISR() - то такое прерывание затягивается дольше чем принимается байт данных, в итоге весь блок портится, т к следующий байт повреждён. На фотографии красный луч показывает длительность нахождения в прерывании. Самый широкий импульс как раз и есть вызов функции SignalISR(). Если закомментировать строчку с вызовом - всё приходит в норму. Но только процесс ничего не знает о событии. На фотографии ниже показана длительнось обработки SPI прерывания без подьёма флагов, примерно 400ns. Вопрос - как победить неувязку? Пока не удаётся разогнать SPI даже до приемлимого уровня... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
blackfin 14 22 февраля, 2010 Опубликовано 22 февраля, 2010 · Жалоба Вы или неверно изложили суть проблемы, или выбрали неверную стратегию обработки данных SPI. Т.е., если "принимается блок данных по SPI", то логично обрабатывать прерывание от канала DMA привязанного к SPI. В этом случае прерывание не может "в итоге испортить весь блок данных", т.к. весь блок данных уже принят и уже сохранен в памяти. Если "такое прерывание" от канала DMA с вызовом функции SignalISR() "затягивается дольше чем принимается байт данных" следующего блока данных, то необходимо просто настроить канал DMA на работу с двумя буферами в памяти с использованием списка или массива дескрипторов. В этом случае, пока Ваше прерывание от первого блока данных вызывает в обработчике функцию SignalISR(), канал DMA уже принимает данные от второго блока и сохраняет эти данные во втором буфере в памяти. Если же Вы вызываете прерывание после каждого принятого по SPI слова, то кроме уменьшения времени обработки в функции SignalISR(), других вариантов вроде как и нет.. Но это не путь Джедая.. Как-то так.. :rolleyes: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Gradient 1 22 февраля, 2010 Опубликовано 22 февраля, 2010 · Жалоба весь блок данных уже принят и уже сохранен в памяти Всё бы хорошо... если блок данных всегда одинаковой длины. Но используются изменяемые длины блоков, в зависимости от ситуации. Ведь нет смысла гнать 2048 байт если надо передать всего 2. Проще ловить заголовок, где сидит команда к дальнейшим действиям, а потом уже что то делать. Верно? Например поднять пин или в этом же пакете выгрузить данные из sdram или flash. Про стратегию - там всё давно продумано. Очень актуален вопрос: "как ускорить поднятие флага события". Ведь за это время можно поднять пару сотен обычных bool флагов... ----------- пс: Вопрос к модераторам. Почему уведомления не отсылаются о новых сообщениях? За последние 2 года ни одного не приходило. :( - Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
blackfin 14 22 февраля, 2010 Опубликовано 22 февраля, 2010 · Жалоба Очень актуален вопрос: "как ускорить поднятие флага события". Речь идет о макросе VDK_ISR_SET_EVENTBIT_(..) или о чем-то другом? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Gradient 1 22 февраля, 2010 Опубликовано 22 февраля, 2010 · Жалоба Речь о scmRTOS функции: void OS::TEventFlag::SignalISR() Функция определена в файле OS_SERVICES_H как INLINE inline void SignalISR(); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
blackfin 14 22 февраля, 2010 Опубликовано 22 февраля, 2010 · Жалоба Речь о scmRTOS функции: void OS::TEventFlag::SignalISR() Функция определена в файле OS_SERVICES_H как INLINE inline void SignalISR(); А.. Ну это не ко мне.. это к dxp.. :rolleyes: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Gradient 1 22 февраля, 2010 Опубликовано 22 февраля, 2010 · Жалоба Видимо вопрос к разработчикам scmRTOS, т к в такие тонкости мало кто вникает... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 32 22 февраля, 2010 Опубликовано 22 февраля, 2010 · Жалоба Собственно трудность заключается в медленном поднятии флага при вызове функции SignalISR(). Разместил флаги в секции "l2_var", функцию SignalISR() в секции "drivers_L1_code" Но это не помогло решить проблему. Странное поведение. Функция-то очень простая: void OS::TEventFlag::SignalISR() { TCritSect cs; if(ProcessMap) // if any process waits for event { TProcessMap Timeouted = Kernel.ReadyProcessMap; // Process has its tag set in ReadyProcessMap if timeout // expired, or it was waked up by OS::ForceWakeUpProcess() if( ProcessMap & ~Timeouted ) // if any process has to be waked up { SetPrioTag(Kernel.ReadyProcessMap, ProcessMap); // place all waiting processes to the ready map ClrPrioTag(ProcessMap, ~Timeouted); // remove all non-timeouted processes from the waiting map. return; } } Value = efOn; } тут негде тормозить. Вот реализация в моем проекте (буков много, но по коду там совсем чуть): _SignalISR__Q2_2OS10TEventFlagFv: .LN_SignalISR__Q2_2OS10TEventFlagFv: .LN12: unsigned int __rval = __builtin_cli(); // line "D:\CAD\AD\VisualDSP5.0\Blackfin\include\builtins.h":1762 P1 = R0; .LN13: { // line "scmRTOS\Common\OS_Services.h":237 LINK 0; .LN14: unsigned int __rval = __builtin_cli(); // line "D:\CAD\AD\VisualDSP5.0\Blackfin\include\builtins.h":1762 .MESSAGE/SUPPRESS 5515; CLI R1; I0 = R0; .LN15: TCritSect () : StatusReg(cli()) { } // line "scmRTOS\Blackfin\OS_Target.h":109 W[sP + 8] = R1; .LN16: if(ProcessMap) // if any process waits for event // line "scmRTOS\Common\OS_Services.h":239 R0 = W[P1] (Z); CC = R0 == 0; if CC jump .P41L27 ; .P41L1: P0.L = _Kernel__2OS+2; P0.H = _Kernel__2OS+2; NOP; // Inserted 2 instrs to fix anomaly w05_00_0245_with_boundaries. NOP; .LN17: TProcessMap Timeouted = Kernel.ReadyProcessMap; // Process has its tag set in ReadyProcessMap if timeout // line 241 R2 = W[P0] (Z); .LN18: if( ProcessMap & ~Timeouted ) // if any process has to be waked up // line 243 R1 = -1; R1 = R2 ^ R1; R0 = R0 & R1; CC = R0 == 0; if !CC jump .P41L13 ; .P41L27: .LN19: Value = efOn; // line 250 R0 = 1; [P1 + 4] = R0; .LN20: ~TCritSect() { sti(StatusReg); } // line "scmRTOS\Blackfin\OS_Target.h":110 R0 = W[sP + 8] (Z); .LN21: __builtin_sti(__a); // line "D:\CAD\AD\VisualDSP5.0\Blackfin\include\builtins.h":1777 .MESSAGE/RESTORE 5515; STI R0; .P41L7: .LN22: return; // line "scmRTOS\Common\OS_Services.h":247 P0 = [FP + 4]; UNLINK; // -- 2 stalls -- JUMP (P0); .P41L13: .LN23: SetPrioTag(Kernel.ReadyProcessMap, ProcessMap); // place all waiting processes to the ready map // line 245 R0.L = W[i0]; .LN24: INLINE inline void SetPrioTag(TProcessMap& pm, const TProcessMap PrioTag) { pm |= PrioTag; } // line "scmRTOS\Common\OS_Kernel.h":81 R1.L = W[P0]; .LN25: R0 = R0 | R1; .LN26: W[P0] = R0.L; .LN27: INLINE inline void ClrPrioTag(TProcessMap& pm, const TProcessMap PrioTag) { pm &= ~PrioTag; } // line 82 R0.L = W[i0]; .LN28: R0 = R2 & R0; .LN29: W[i0] = R0.L; .LN30: ~TCritSect() { sti(StatusReg); } // line "scmRTOS\Blackfin\OS_Target.h":110 R0 = W[sP + 8] (Z); .LN31: __builtin_sti(__a); // line "D:\CAD\AD\VisualDSP5.0\Blackfin\include\builtins.h":1777 .MESSAGE/RESTORE 5515; STI R0; jump .P41L7; Провел замеры на текущем проекте. 1. Время выполнения самой функции SignalISR. ... START_CYCLE_COUNT(start_count); GIFH_complete.SignalISR(); STOP_CYCLE_COUNT(stop_count, start_count); print("cycles: %d\r", stop_count); ... получил значение 62 цикла. Значение это, думаю, не очень точное, т.к. на такой малой величине сильно влияют накладные расходы на эти макросы. 2. Время от начала SignalISR до Wait. // fpga.cpp ... START_CYCLE_COUNT(start_count); GIFH_complete.SignalISR(); ... // video.cpp ... GIFH_complete.Wait(); STOP_CYCLE_COUNT(stop_count, start_count); print("cycles: %d\r", stop_count); ... Полученное значение - 363 цикла, что при тактовой 200 МГц составляет порядка 1.8 мкс, что похоже на время из примера - порядка 1.5-1.6 мкс (там у меня еще часть кода выполняется, поэтому время чуть больше). Попробуйте так же замерить. Сколько сама функция, сколько время передачи управления в ожидающий процесс. Какая у вас тактовая частота? На какой скорости SPI гоняете? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Gradient 1 22 февраля, 2010 Опубликовано 22 февраля, 2010 (изменено) · Жалоба Какая у вас тактовая частота? На какой скорости SPI гоняете? core speed = 600mHz system speed =(600mHz/8) = 75mHz скорость SPI видно по осциллограмме, период тактовой ~1.8 mks Это эмуляция spi протокола через USB FT232R на скорости 921600, реальная байтовая скорость = /8/2 Попробую померить. Изменено 22 февраля, 2010 пользователем sevstels Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Gradient 1 22 февраля, 2010 Опубликовано 22 февраля, 2010 · Жалоба Перенёс флаги в L1. Измерил. Непосредственно сама функция SignalISR выполняется около 320ns. CLR_LED; flag_SPI_HeaderAccepted.SignalISR(); SET_LED; Теперь от начала вход и до выхода из прерывания около 1.2us в самом худшем случае. Спасибо за подсказку dxp, хорошая методика. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
blackfin 14 22 февраля, 2010 Опубликовано 22 февраля, 2010 · Жалоба Тоже сделал замеры при вызове макросов VDK на достаточно большом проекте: VDK_ISR_POST_SEMAPHORE_() - 475 CYCLES, VDK_ISR_SET_EVENTBIT_() - 540 CYCLES. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Gradient 1 22 февраля, 2010 Опубликовано 22 февраля, 2010 · Жалоба Всё равно - нет в жизни счастья. Звенит тактовый сигнал с FT232, не пойму почему. Видно пролазит где то внутри в чипе. Появляются лишние переходы и данные "плывут". Блок 2048 байт не удаётся передать правильно на полной скорости. :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
blackfin 14 22 февраля, 2010 Опубликовано 22 февраля, 2010 (изменено) · Жалоба Блок 2048 байт не удаётся передать правильно на полной скорости. :( Я же говорю, у Вас сомнительная стратегия.. Даже если Вам удастся "передать правильно на полной скорости" весь блок, и если Вы собираетесь делать это на регулярной основе, все МИПС-ы Вашего процессора будут растрачены на обработку прерываний от SPI. На собсно полезную работу сил ему уже не хватит.. ИМХО.. ;) Изменено 22 февраля, 2010 пользователем blackfin Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Gradient 1 22 февраля, 2010 Опубликовано 22 февраля, 2010 · Жалоба Нет необходимости вообще что либо делать, кроме как переливать из НАНД по SPI-USB в компьютер. Это отдельный режим, используемый крайне редко. Поэтому все мипсы могут быть пущены в расход. Главный критерий тут - скорость. Маленькими блоками по 256 байт нормально работает. Но проблема, что приходится чаще дёргать USB, а там как минимум 20мс пауза между передачами. Задержка на файле 1МВ получается очень существенная. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Gradient 1 22 февраля, 2010 Опубликовано 22 февраля, 2010 (изменено) · Жалоба дел Изменено 22 февраля, 2010 пользователем sevstels Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться