Такое прерывание можно еще оптимизировать?
- Войдите на сайт для отправки комментариев
Ср, 06/07/2022 - 00:01
Добрый день.
Есть желание сделать прерывание по возможности оптимальнее по времени выполнения.
Оно крутит шаговый двигатель и считает шаги, которые использует осн тело программы.
#define MainStStep 8 ISR(TIMER1_B) { s1 = not(s1); bitWrite(PORTB, MainStStep-8, s1); Steps++; }
78125, дизассемблировать надо, и посмотреть во что выливается этот конкретный фрагмент в листинге , может что немного можно ужать. А радикально оптимизировать -только через ISR_NAKED и на ассемблере вручную пуш-попить только необходимые регистры в стек. Но обычно кто такое сам может сделать, тот и не спрашивает :)
По моему сначала надо определить (рассчитать) допустимое время выполнения прерывания. И если укладывается, то код уже оптимальный по некоторым критериям.
Можно вообще обойтись без прерываний, выход менять аппаратно по PWM, а количество - аппаратно вторым таймером, подав ему на вход эти импульсы. Но будет ли это оптимально?
"Toggling the Pin.
Writing a logic one to PINxn toggles the value of PORTxn, independent on the value of DDRxn. Note that the SBI instruction can be used to toggle one single bit in a port."
Плюс ISR_NAKED как dimax уже описал.
Steps какой тип имеет ?
... дизассемблировать надо ...
Откомпилировать с формированием листинга и глянуть листинг...
Эта жуть для long Steps...
Дарю код для long Seps...
Строки с 10 по 18 надо удалять в зависимости от типа Steps...
На выходе вот такой листинг:
Ты сэкономил 3 пуша и 3 попа, то есть 12 тактов. Я имею ввиду не на всем прерывании, а на работе с лонг переменной. 750 наносек. Все норм и красиво, но херней этой заниматься имеет смысл тогда, когда тебе есть кому продать сэкономленные такты. Не в шутку, а на самом деле - операция критична по времени и вот этой самой микросекунды как раз не хватало!
Лезть в ассемблер без нужды? Мне кажется, что даже в хобби результат важнее процесса, но кому - как. ;)) В теории могу представить человека, который покрывает ломберный столик 12-ым слоем лака и вручную шлифует его какой-то волшебной шкуркой из крови единорога и перхоти девственницы! ;))) Вот так и с программированием и ассемблером.
... 3 пуша и 3 попа, ...
Как то странно вы посчитали ...
... 3 пуша и 3 попа, ...
Как то странно вы посчитали ...
Я имею ввиду не на всем прерывании, а на работе с лонг переменной.
Что тебе не ясно? Оба эти кода - 20 тактов. Разница в регистрах. Ты использовал 1, а компилятор черыре, на 6 команд == на 12 тактов больше при входе/выходе из прерывания. Что-то еще посчитать за тебя?
Ух спасибо.)
Пожалуй ассембер это уже перебор.
Я правильно понял, что могу эти 2 строки заменить одной: переключения пина на инверсное значение?
Ух спасибо.)
Пожалуй ассембер это уже перебор.
Я правильно понял, что могу эти 2 строки заменить одной: переключения пина на инверсное значение?
да!
Странные люди! Ну проверь... хоть в эмуляторе, типа wokwi.com. Неужели проще вопрос задать, чем проверить самому?
уже! спасибо.
а можно хоть какой то комментарий как это работает? Битовый сдвиг из единицы?
Нашел такое https://github.com/AlexGyver/GyverCore/issues/15
"запись в PINx (на ATmega48/88/168/328) инвертирует состояние на выходе.
меняем на...
"
В
bitSet как то проще))Какая разница ассемблер или нет, когда тебе дали готовый код ? Это же INLINE ASM - вставляется и компилируется прямо из C/C++
Да легко!
А остальное делать в программе.
уже! спасибо.
а можно хоть какой то комментарий как это работает? Битовый сдвиг из единицы?
Нашел такое https://github.com/AlexGyver/GyverCore/issues/15
"запись в PINx (на ATmega48/88/168/328) инвертирует состояние на выходе.
меняем на...
"
В
bitSet как то проще))Да легко!
А остальное делать в программе.
Не пойдет, прерывание вызывается достаточно часто, до обработкив теле программы может не успеть дойти, пока вызовется второе прерывание, которое снова поставит flag и при подсчете шагов, один шаг уже будет потерян.
78125 Steps какого типа у вас ?
Тогда ничего менять в том моём коде на ASM не надо. В AVR нет команды на прибавление непосредственного значения - по этому используется вычитание: Steps+1 = Steps-(-1). -1 для long это 0xFFFFFFFF - вот его и вычитаем из всех байтов по очереди с учетом возможного переноса/заёма ...
Спасибо!
Можно конечно вставить проверку на перенос/заём после каждого вычитания, но тогда время нахождения в прерывании будет отличаться в зависимости от того сколько раз произошёл перенос/заём...
А вообще, оно надо 4-байтовый Steps в прерывании теребить? Может выделить под это один счётный регистр Rx, его в прерывании инкрементировать, а в лупе уже приплюсовывать его к Steps. Тогда прерывание ещё в несколько раз ужмётся)
А вообще, оно надо 4-байтовый Steps в прерывании теребить? Может выделить под это один счётный регистр Rx, его в прерывании инкрементировать, а в лупе уже приплюсовывать его к Steps. Тогда прерывание ещё в несколько раз ужмётся)
Если две-три мкс имеют значение, видимо, нужно перепроектировать изделие? Не те времена, чтобы вытягивать из "дорогущего" микроконтроллера предел его возможностей. ;)