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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> SignalISR() в Blackfin, флаг устанавливается медленно
sevstels
сообщение Feb 22 2010, 04:19
Сообщение #1


Знающий
****

Группа: Участник
Сообщений: 626
Регистрация: 3-12-07
Пользователь №: 32 910



Собственно трудность заключается в медленном поднятии флага при вызове функции SignalISR().
Разместил флаги в секции "l2_var", функцию SignalISR() в секции "drivers_L1_code"
Но это не помогло решить проблему.

Принимаются блок данных по SPI, после корректного приёма заголовка должен устанвливаться флаг события. Если в коде обработчика прерывания от SPI по совпадению условий вызывается SignalISR() - то такое прерывание затягивается дольше чем принимается байт данных, в итоге весь блок портится, т к следующий байт повреждён. На фотографии красный луч показывает длительность нахождения в прерывании. Самый широкий импульс как раз и есть вызов функции SignalISR().
Если закомментировать строчку с вызовом - всё приходит в норму. Но только процесс ничего не знает о событии.




На фотографии ниже показана длительнось обработки SPI прерывания без подьёма флагов, примерно 400ns.
Вопрос - как победить неувязку? Пока не удаётся разогнать SPI даже до приемлимого уровня...



--------------------
Herz - дятел.
Go to the top of the page
 
+Quote Post
blackfin
сообщение Feb 22 2010, 05:09
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 3 106
Регистрация: 18-04-05
Пользователь №: 4 261



Вы или неверно изложили суть проблемы, или выбрали неверную стратегию обработки данных SPI.

Т.е., если "принимается блок данных по SPI", то логично обрабатывать прерывание от канала DMA привязанного к SPI. В этом случае прерывание не может "в итоге испортить весь блок данных", т.к. весь блок данных уже принят и уже сохранен в памяти.

Если "такое прерывание" от канала DMA с вызовом функции SignalISR() "затягивается дольше чем принимается байт данных" следующего блока данных, то необходимо просто настроить канал DMA на работу с двумя буферами в памяти с использованием списка или массива дескрипторов. В этом случае, пока Ваше прерывание от первого блока данных вызывает в обработчике функцию SignalISR(), канал DMA уже принимает данные от второго блока и сохраняет эти данные во втором буфере в памяти.

Если же Вы вызываете прерывание после каждого принятого по SPI слова, то кроме уменьшения времени обработки в функции SignalISR(), других вариантов вроде как и нет.. Но это не путь Джедая..

Как-то так.. rolleyes.gif
Go to the top of the page
 
+Quote Post
sevstels
сообщение Feb 22 2010, 05:32
Сообщение #3


Знающий
****

Группа: Участник
Сообщений: 626
Регистрация: 3-12-07
Пользователь №: 32 910



Цитата
весь блок данных уже принят и уже сохранен в памяти

Всё бы хорошо... если блок данных всегда одинаковой длины.
Но используются изменяемые длины блоков, в зависимости от ситуации. Ведь нет смысла гнать 2048 байт если надо передать всего 2.
Проще ловить заголовок, где сидит команда к дальнейшим действиям, а потом уже что то делать. Верно?
Например поднять пин или в этом же пакете выгрузить данные из sdram или flash.
Про стратегию - там всё давно продумано.
Очень актуален вопрос: "как ускорить поднятие флага события". Ведь за это время можно поднять пару сотен обычных bool флагов...

-----------
пс: Вопрос к модераторам.
Почему уведомления не отсылаются о новых сообщениях?
За последние 2 года ни одного не приходило. sad.gif

-


--------------------
Herz - дятел.
Go to the top of the page
 
+Quote Post
blackfin
сообщение Feb 22 2010, 05:40
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 3 106
Регистрация: 18-04-05
Пользователь №: 4 261



Цитата(sevstels @ Feb 22 2010, 08:32) *
Очень актуален вопрос: "как ускорить поднятие флага события".

Речь идет о макросе VDK_ISR_SET_EVENTBIT_(..) или о чем-то другом?
Go to the top of the page
 
+Quote Post
sevstels
сообщение Feb 22 2010, 05:45
Сообщение #5


Знающий
****

Группа: Участник
Сообщений: 626
Регистрация: 3-12-07
Пользователь №: 32 910



Речь о scmRTOS функции: void OS::TEventFlag::SignalISR()
Функция определена в файле OS_SERVICES_H как INLINE inline void SignalISR();


--------------------
Herz - дятел.
Go to the top of the page
 
+Quote Post
blackfin
сообщение Feb 22 2010, 05:48
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 3 106
Регистрация: 18-04-05
Пользователь №: 4 261



Цитата(sevstels @ Feb 22 2010, 08:45) *
Речь о scmRTOS функции: void OS::TEventFlag::SignalISR()
Функция определена в файле OS_SERVICES_H как INLINE inline void SignalISR();

А.. Ну это не ко мне.. это к dxp.. rolleyes.gif
Go to the top of the page
 
+Quote Post
sevstels
сообщение Feb 22 2010, 05:52
Сообщение #7


Знающий
****

Группа: Участник
Сообщений: 626
Регистрация: 3-12-07
Пользователь №: 32 910



Видимо вопрос к разработчикам scmRTOS, т к в такие тонкости мало кто вникает...


--------------------
Herz - дятел.
Go to the top of the page
 
+Quote Post
dxp
сообщение Feb 22 2010, 08:15
Сообщение #8


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(sevstels @ Feb 22 2010, 10:19) *
Собственно трудность заключается в медленном поднятии флага при вызове функции 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;
}


тут негде тормозить. Вот реализация в моем проекте (буков много, но по коду там совсем чуть):

CODE

_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 гоняете?


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
sevstels
сообщение Feb 22 2010, 08:38
Сообщение #9


Знающий
****

Группа: Участник
Сообщений: 626
Регистрация: 3-12-07
Пользователь №: 32 910



Цитата
Какая у вас тактовая частота? На какой скорости SPI гоняете?


core speed = 600mHz
system speed =(600mHz/8) = 75mHz
скорость SPI видно по осциллограмме, период тактовой ~1.8 mks
Это эмуляция spi протокола через USB FT232R на скорости 921600, реальная байтовая скорость = /8/2

Попробую померить.

Сообщение отредактировал sevstels - Feb 22 2010, 08:47


--------------------
Herz - дятел.
Go to the top of the page
 
+Quote Post
sevstels
сообщение Feb 22 2010, 11:00
Сообщение #10


Знающий
****

Группа: Участник
Сообщений: 626
Регистрация: 3-12-07
Пользователь №: 32 910



Перенёс флаги в L1. Измерил.
Непосредственно сама функция SignalISR выполняется около 320ns.

Код
CLR_LED;
flag_SPI_HeaderAccepted.SignalISR();
SET_LED;


Теперь от начала вход и до выхода из прерывания около 1.2us в самом худшем случае.


Спасибо за подсказку dxp, хорошая методика.


--------------------
Herz - дятел.
Go to the top of the page
 
+Quote Post
blackfin
сообщение Feb 22 2010, 12:54
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 3 106
Регистрация: 18-04-05
Пользователь №: 4 261



Тоже сделал замеры при вызове макросов VDK на достаточно большом проекте:

VDK_ISR_POST_SEMAPHORE_() - 475 CYCLES,

VDK_ISR_SET_EVENTBIT_() - 540 CYCLES.
Go to the top of the page
 
+Quote Post
sevstels
сообщение Feb 22 2010, 13:29
Сообщение #12


Знающий
****

Группа: Участник
Сообщений: 626
Регистрация: 3-12-07
Пользователь №: 32 910



Всё равно - нет в жизни счастья.
Звенит тактовый сигнал с FT232, не пойму почему. Видно пролазит где то внутри в чипе. Появляются лишние переходы и данные "плывут". Блок 2048 байт не удаётся передать правильно на полной скорости. sad.gif


--------------------
Herz - дятел.
Go to the top of the page
 
+Quote Post
blackfin
сообщение Feb 22 2010, 13:58
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 3 106
Регистрация: 18-04-05
Пользователь №: 4 261



Цитата(sevstels @ Feb 22 2010, 16:29) *
Блок 2048 байт не удаётся передать правильно на полной скорости. sad.gif

Я же говорю, у Вас сомнительная стратегия.. Даже если Вам удастся "передать правильно на полной скорости" весь блок, и если Вы собираетесь делать это на регулярной основе, все МИПС-ы Вашего процессора будут растрачены на обработку прерываний от SPI. На собсно полезную работу сил ему уже не хватит.. ИМХО.. wink.gif

Сообщение отредактировал blackfin - Feb 22 2010, 13:59
Go to the top of the page
 
+Quote Post
sevstels
сообщение Feb 22 2010, 14:45
Сообщение #14


Знающий
****

Группа: Участник
Сообщений: 626
Регистрация: 3-12-07
Пользователь №: 32 910



Нет необходимости вообще что либо делать, кроме как переливать из НАНД по SPI-USB в компьютер. Это отдельный режим, используемый крайне редко. Поэтому все мипсы могут быть пущены в расход. Главный критерий тут - скорость. Маленькими блоками по 256 байт нормально работает. Но проблема, что приходится чаще дёргать USB, а там как минимум 20мс пауза между передачами. Задержка на файле 1МВ получается очень существенная.


--------------------
Herz - дятел.
Go to the top of the page
 
+Quote Post
sevstels
сообщение Feb 22 2010, 14:52
Сообщение #15


Знающий
****

Группа: Участник
Сообщений: 626
Регистрация: 3-12-07
Пользователь №: 32 910



дел

Сообщение отредактировал sevstels - Feb 22 2010, 14:54


--------------------
Herz - дятел.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 30th June 2025 - 17:27
Рейтинг@Mail.ru


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