Форум обсуждения систем  

Вернуться   Форум обсуждения систем "Умный дом", проектов Ардуино, OpenWRT и других DIY устройств > Форум умного дома > Сделай сам

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 22.06.2015, 09:48   #11
Arhat109
Senior Member
 
Регистрация: 14.06.2015
Адрес: СССР
Сообщений: 122
Вес репутации: 0
Arhat109 is an unknown quantity at this point
По умолчанию Re: Ускоряем и улучшаем скетчи. Ещё одна библиотека.

Пасибки всем кто откликнулся, но к решению проблемы меня это не приблизило ни разу.

Теперь библиотека позволяет компилять стандартный Blink.ino в размер аж 502 байта... но вот только "не пашет" как надо.

Что делал и как (файл arhat_time.c):

1. Проверка обработчика прерывания (код теста в примерах) - читаем тупо счетчик прерываний таймера по переполнению и считаем задержки по его значениям. Всё пашет как надо. Но он считает по 1.024 миллисекунды, а стало быть задержки НЕ миллисекундные. Можно пользоваться только им, но тогда свои чиселки из миллисекунд надо пересчитывать в тики таймера вручную, на куркуляторе.

Обработчик прерываний минимизирован "до не могу" и работает верно. Заодно, уменьшается требование к оперативке: нет хранения fract и счетчика миллисекунд. Экономия 5 байт оперативы.

2. Начальная инициализация скетча: устранены все предварительные настройки таймеров из функции init(), которая подшивается в типовом main() принудительно. Только настройка таймера 0. За счет константной настройки, можно перекомпилять "по другому" и потом использовать "как хочется", и дополнительно от init() осталось ... 26 байт кода.

Дополнительно сделан макрос pwmSet(pin), который надо использовать в setup(), для добавления настроек нужного таймера. Фактически, какие ноги под аппаратный PWM используем - настройка таких счетчиков и будет добавлена, но уже в setup().

Для полноты, добавлен макрос pwmOff(pin), отключающий таймер и ногу.

3. Функция micros() реализована ассемблерной вставкой, устраняющей косяк компилятора. Точнее, его слабую оптимизацию переиспользования регистров и отсутствие байтовой компиляции "длинных чисел", при том, что контроллер - таки байтовый. Эта же оптимизация ручками использована и в обработчике прерывания по переполнению.

Вот тут - я сильно не уверен, что поступил верно. Поскольку в asm-вставке не указано никак, что функция использует стек и прячет и достает "всё что портит". Из-за этого, её пришлось увеличить на 8 байт. Но, глядя на листинг ассемблера, хорошо вижу что компилируется верно.

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

... требуется детальная перепроверка, может её кто-то сделать?

К сожалению, эта функция, точно также как и стандартный millis() совершенно непригодна для формирования решений методом % (кратно значению микросекунд от начала счета), типа так:

if( micros() % 500 ) { /*...код...*/ }

поскольку её результат "скачет" далеко не подряд... сам счетчик кратен 4 микросекундам, плюсом идет насчет собственного времени работы. Вот чиселко в ovf_count - использовать ТАК - очень даже можно...

Для этого, добавлена функция getOvfCount(), считывающая его значение при запрещенных прерываниях (консистентно). По-хорошему, надо бы превратить в макрос для inline вставок в код "по желанию"... (скорость/размер)

3. Функция millis() - проверял раньше, работала, более не изменял. Ибо - это "затычка". В отличии от стандартной, она пересчитывает текущее состояние счетчика переполнений с учетом текущего состояния счетчика и использует библиотеку деления длинных целых чисел. Это ни разу не быстро, поэтому её активное использование - сильно не рекомендуется.

Но, предпочитаю иметь пусть долгую, но верно работающую функцию, чем нечто косячное... тут, что называется "на вкус и цвет". Если нужна именно эта и "быстрая", то проще оставить типовой wiring.c вместо файла arhat_time.c

Тут требуется мнение сообщества "что нужнее"?

4. Функция delay(). Реализована в двух вариантах: с параметром unsigned long (по сути, полная копия из wiring.c) и параметром unsigned int (uint16_t).

Обе функции имеют собственные названия с префиксом: time_delay(uint32_t) и time_delay16(uint16_t) и в стандартный delay() переименовываются препроцессором согласно режиму либы.

Вот они обе, работают сейчас неверно и я не могу понять "в чем дело".

Смотрел ассемблерный листинг, и в нем тоже "всё ровно": обрезка значения происходит верно: тупо после вызова time_micros() использовано только 16 младших бит, сравнение вроде как с константой в 16бит ... может конечно "не то", я ещё плохо ориентируюсь в ассемблерных командах... Больше опасался, что асм-реализация micros как-то криво подшивается в вызов ... но нет, все тоже вроде бы "ровно".

Может кто-нибудь скомпилировать вручную arhat_time.c в ассемблер и посмотреть "что там не так"? (может мне ещё не по глазам?) Ну или погонять под отладчиком и/или имитатором ... (уже смотрю в сторону virtualbox, чтобы поставить себе нормальный софт ... пока только линуксовый блокнот, консоль и сама Ардуино ИДЕ)

P.S. Извиняюсь за большой пост, можно использовать как начало описания функций библиотеки (позже добавлю полный хелп и кейвордс, они уже делаются)

Последний раз редактировалось Arhat109; 22.06.2015 в 09:56. Причина: правка очепяток.
Arhat109 вне форума   Ответить с цитированием
 

Метки
arduino mega 2560, скетч, ардуино


Здесь присутствуют: 5 (пользователей: 0 , гостей: 5)
 

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход


Текущее время: 19:30. Часовой пояс GMT +3.


Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Яндекс.Метрика