dpatrakov
Участник-
Постов
26 -
Зарегистрирован
-
Посещение
Репутация
0 ОбычныйИнформация о dpatrakov
-
Звание
Участник
-
плюс одна команда включить пин в начале кода, одна команда выключить в конце, одна перейти в начало петли Проблема частично решена, частично благодаря рассуждениям jcxz правда диалог с ним не получился и зашел в тупик, прерывание запустил с частотой почти 1,5 МГц, но это сожрало 50% ресурса контроллера только на вход и выход но зато получил четкое время накладных расходов прерывания (вход, выход, обслуживание и походу перезеагрузка prefetch в 600-700 ns), также ранее не задумывавшись о передаче данных внутри контроллера так вопрос максимально быстрого отклика отсутствовал, выяснил следующее, буферизации на шинах APB0 и 1 похоже нету, хотя в мануале написано что есть, но может неправильно понял нерусский язык, хотя читаю вроде неплохо, в общем решил отказаться от использования более одного регистра сравнения, и запускать таймер только в режиме сравнения и сброса TC, ну по крайне мере в текущем проекте, хотя отказ от 3 регистров сравнения повлечет изменение алгоритма сильное. Второе выяснилось то что регистр GPIO->FIOPIN имеет буфер записи, с задержкой 2 такта, то есть если записать в него и следующей командой прочитать (на ассемблере) получим предыдущее состояние, добавление 2 nop между записью и чтением решает проблему, хотя такая ситуация редка и в большинстве случаев ее можно избежать. И еще нашел ускорение работы с массивом структур за счет выравнивания руками а не средствами компилятора код занимавший 15 операций (ASM), снизился до 11 за счет выравнивания к 4 не только размеров полей структуры , но и их количества
-
Вот думал тут, на шине где висит таймер, есть другие устройства и время от времени занимают его что соответственно при обращении должно вызвать ожидание, но в этом случае период выполнения был бы плавающим, а он стоит как вкопанный, щас попозже на работу съезжу сфотографирую, и как вариант отключу всю периферию кроме на шине
-
Ну у меня с этого и началось. При возникновении прерывания, TC==MR0, тоесть после проверки флага и его сброса что занимает 12 тактов плюс 12 тактов на сохранение регистров при вызове обработчика TC должен опередить MR0 на 24 такта, а по факту опережает на 75 согласен что при входе в обработчик переписывается префетч, но в простом цикле тот же результат Да еще изменение частоты тактирования таймера не влияет на результат О этот пост я пропустил. мальчик ты чего раздухарился так? ты вообще понимаешь как найти время выполнения конкретной инструкции? похоже что нет вот ты jcxz дофига умный расчитай время выполнения следующего кода ;;;1257 while (1) 000128 e011 B |L1.334| |L1.298| ;;;1258 { ;;;1259 f=1-f; 00012a f1c40401 RSB r4,r4,#1 ;;;1260 if (f) LPC_GPIO0->FIOCLR = 1; 00012e b11c CBZ r4,|L1.312| 000130 2001 MOVS r0,#1 000132 4919 LDR r1,|L1.408| 000134 61c8 STR r0,[r1,#0x1c] 000136 e002 B |L1.318| |L1.312| ;;;1261 else LPC_GPIO0->FIOSET = 1; 000138 2001 MOVS r0,#1 00013a 4917 LDR r1,|L1.408| 00013c 6188 STR r0,[r1,#0x18] |L1.318| ;;;1262 LPC_TIM0->MR0 += 1000; 00013e f04f2040 MOV r0,#0x40004000 000142 6980 LDR r0,[r0,#0x18] 000144 f500707a ADD r0,r0,#0x3e8 000148 f04f2140 MOV r1,#0x40004000 00014c 6188 STR r0,[r1,#0x18] |L1.334| 00014e e7ec B |L1.298| ;;;1263 }
-
200 килогерц прерывание работает, и выполняет свою функцию, но 3 операции по обслуживанию прерывания, занимаю столько времени как весь код самого обработчика ну естественно 1мкс вход выход и непонятные задержки, и десяток команд это 100-150 нс, еще и основному потоку остается время правда мало, вставь в такое прерывание вычисление корня и оно у тебя повиснет, а с десятком команд у меня до 800кГц получалось
-
дак снижена до 48МГц, но не до 4х же пробовал и просто запись и просто чтение дает 250нс, чтение модификация запись соответственно 500
-
в документации написано что для общения с периферией буферизированная запись для того чтобы не ждать ну пусть он их вставит, но не 25 тактов же
-
250 нс не беда, но когда выполняются 3 такие инструкции подряд, плюс время входа и выхода из прерывания это 1 мкс, это дофига. 1 МГц мне не нужен, я писал ранее, нужно 200 кГц, но это тоже не мало. самая медленная операция в прерывании это посчитать теорему пифагора для 6мерного пространства тоесть корень из суммы 6квадратов Вы что издеваетесь? в первом посте все написано, меряю все цифровым осциллографом, ножкой для этого и дергаю
-
мне надо каждый раз период перестраивать А во вторых в таймере 4 регистра сравнения, их нужно проверить и сбросить флаги при необходимости, и вот каждая из этих операций длится 250нс Еще по поводу того что - не читал документацию, не понимаю что делаю прошу заметить что зарегистрировался я 11 лет назад, и за это время всего 18 сообщений, это потому что 11 лет не было вопросов, и за это время прочитаны тысячи документаций и реализовано десятки больших проектов, но вот сейчас наступил на какие то грабли и обратился к залу так сказать.
-
И как это оптимизировать? в цикле я проверяю за сколько времени выполняется код в ассемблере это 5 команд LPC_TIM0->MR0 += 1000; 00012a f04f2040 MOV r0,#0x40004000 -- 1 цикл 00012e 6980 LDR r0,[r0,#0x18] -- 2 цикла 000130 f500707a ADD r0,r0,#0x3e8 -- 1 цикл 000134 f04f2140 MOV r1,#0x40004000 -- 1 цикл 000138 6188 STR r0,[r1,#0x18] -- 2 цикла итого 7 циклов по 10 нс = 70нс, а выполняется за 500 вот в чем вопрос
-
Вы отчего так невнимательны, нервничаете? вот в первом посте было написан пример проверки, выполняется в мэйне с отключенными прерываниями, включено только тактирование периферии while (1) { f = 1-f; if (f) PINSET; else PINCLR; LPC_TIM0->MR0 += T0MR0->interval; } дак вот этот код выполняется за 500нс если из него убрать операция обращения к регистру сравнения LPC_TIM0->MR0 += T0MR0->interval; то время выполнения цикла падает до 85нс на ассемблере цикл занимает 9 инструкций и 5 инструкций вот это LPC_TIM0->MR0 += T0MR0->interval; дак если читали внимательно, я писал что 9 инструкций цикла выполняются за 85 нс а 5 которые записывают в регистр таймера около 500 По поводу флешь, вы что не знали что она требует 5 тактов задержки? значит 20МГц, но этот вариант был проверен сразу, путем отключения ускорителя, во вторых в мэйне код выполняется в одном месте и не прыгает в прерывание, поэтому перезагрузка не требуется
-
И включал и выключал Ну вы видимо тот еще читатель, раз это понаписали, или привыкли считать себя умнее других. Если бы вы внимательно прочитали, то там все подробно написано, и про то что делитель равен 1 уверен на 100%, насчет си исходника ниже написано что компилируется в 12 инструкций ассемблерных, про стекинг было написано выше и это не десятки тактов а 12 то есть 120 нс (видимо плоховато вы знаете контроллер), с чего вы решили что документация не читалась и ваяется ногодрыгалка? Не имейте привычки флудить чтобы сумничать.
-
Таймер висит на шине APB0, тактируется cclk (100МГц) Запустить на мегагерце получается пустое прерывание, но при этом процессор загружен почти на 100% из за выполнения всего трех инструкций if (TIM_GetIntStatus(LPC_TIM0, TIM_MR0_INT)== SET) //250нс { LPC_TIM0->MR0 = m_tc + T0MR0->interval; //500нс TIM_ClearIntPending(LPC_TIM0, TIM_MR0_INT); //250нс } на ассемблере эта конструкция занимает 12 операций тоесть если рассуждать логически то должна отработать за 120нс, а по факту получается 1000нс что в 10 раз больше, остальные инструкции в обработчике если добавить код выполняются примерно за 10нс на картинке 2 пути отмечены, GPIO и таймеры висят на системной шине, к выводам шина напрямую время доступа 10нс, к таймеру через AHB->APB мост и время увеличивается до 250нс, то есть получается скорость работы моста 4МГц? вроде бред, или в документации было бы написано что операции чтения регистров периферии ОЧЕНЬ медленныеи используйте их осторожно Вообще мне мегагерц прерывание не нужно, фактически нужно до 200кГц выполнить нужную задачу, и еще мэйну оставить время для работы, но на такой частоте получаем только операции обслуживания прерывания жрут 20% скорости, а приплюсовав еще один таймер для задержек и пару уартов то наверное и все 50% пропадает
-
Я это в душе понимаю, но как посмотреть? 250нс это 4Мгц таких источников вроде нет
-
Форумчане прошу помощи в поиске проблемы Проблема в следующем, камень запущен на частоте 100 МГц тоесть инструкции должны выполняться за 10нс, дерганье ножкой показывает что примерно так и есть, но вот возникла задача генерить высокую частоту таймером, и больше 1 мегагерца не получилось, хотя по мануалу вход в прерывание занимает 12 тактов или 120 нс, путем тыка найдена инструкции которые выполняются не за 10нс а за целых 250. Вот проблемная команда LPC_TIM0->MR0 += T0MR0->interval; ее выполнение занимает 500 нс, это не то что медленно, а вообще жесть. в ассемблере это занимает всего 4 инструкции (загрузка адреса, чтение, сложение, выгрузка обратно) в итоге прерывание даже пустого таймера выполняется за 750 нс плюс 120нс вход и 120 выход тоесть 1мкс. 750 получается из 1) операция проверки флага mr0 2) сброс флага 3) изменение mr0 Вторую проверку проводил так while (1) { f = 1-f; if (f) PINSET; else PINCLR; LPC_TIM0->MR0 += T0MR0->interval; } итог период выполнения ~600 нс while (1) { f = 1-f; if (f) PINSET; else PINCLR; //LPC_TIM0->MR0 += T0MR0->interval; } период выполнения ~85нс ассемблере тесты различаются всего на 4 инструкции еще тест while (1) { f = 1-f; if (f) PINSET; else PINCLR; LPC_TIM0->MR0 = T0MR0->interval; } итог период выполнения ~300 нс если рассуждать логически то включение ноги процессора это банальная операция записи в ячейку памяти соответствующую GPIO, а запись в регистр сравнения это такая же операция записи числа в ячеку памяти, но одна выполняется за 10 нс другая аж за 250 Встал в ступор куда копать не знаю
-
Огромное спасибо, то что нужно