![]() |
![]() |
#11 |
Senior Member
Регистрация: 14.06.2015
Адрес: СССР
Сообщений: 122
Вес репутации: 0 ![]() |
![]()
Пасибки всем кто откликнулся, но к решению проблемы меня это не приблизило ни разу.
![]() Теперь библиотека позволяет компилять стандартный 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. Причина: правка очепяток. |
![]() |
![]() |
Метки |
arduino mega 2560, скетч, ардуино |
Здесь присутствуют: 1 (пользователей: 0 , гостей: 1) | |
Опции темы | Поиск в этой теме |
Опции просмотра | |
|
|