И еще: из обработчика прерываний крайне нежелательно вызывать другие функции, тем более с параметрами. Но если уж очень хочется, делайте все эти вызываемые из прерывания функции static, и, по возможности, ниоткуда более их не вызывайте.
Это (во многих случаях) вредный совет. Функции бывают реентерабельные и нереетерабельные. Например, что мешает вызвать memset () из обработчика прерывания, если "заливаемая" область памяти используется только в этом обработчике? Она (функция memset () ) и глобальная, и с параметрами и много откуда вызывается. Что надо функционал memset () в обработчик переносить?
Обработчик прерывания - это фактически еще один "поток" выполнения, который выполняется одновременно с основным потоком (в принципе, одновременно может выполняться много потоков, больше, чем два: основной и обработчик - это сейчас не важно). Функции могут быть потокобезопасными, а могут и не быть таковыми. Потокобезопасные функции можно вызывать из одновременно выполняющихся потоков, так как потокобезопасные функции упорядочивают доступ к общим данным (если таковые имеются). Соответственно, потокобезопасную функцию можно вызывать из обработчика (пока не рассматриваем функции, которые ждут какого либо события, например, нажатия кнопки пользователем - понятно, что ждать нажания кнопки в обработчике нельзя).
Пока_без_кота, вот тебе еще "грабли" (так на всякий случай ). Про атомарнось. volatile к атомарности не имеет никакого отношения. Присвоение значения указателю parsing_pointer - это неатомарная операция (прерывание может возникнуть, когда операция начала выполняться, но не завершилась). Как минимум две ассемблерные команды нужно, чтобы сохранить значение 16-ти битного указателя. Если прерывания разрешены и в обработчике используется parsing_pointer, обработчик может быть вызван между сохранением "половинок" указателя parsing_pointer. Такую ошибку найти черезвычайно трудно (может неделями и месяцами не проявляться).
это в применении к AVR практически всегда безусловно правильный совет. вы как-то совсем упускаете из виду, что главный ресурс AVR, который стоит беречь всеми силами, это ОЗУ. так вот, использование не-static функций в обработчике прерывания приводит к тому, что в стеке сохраняется слишком много регистров, а в случае с вызовом функций из других модулей или библиотечных, будут сохранены в стеке вообще все рабочие регистры. и кому это надо? а вот static-функции практически со 100% вероятностью будут проинлайнены и не смотря на количество передаваемых параметров обеспечат наиболее экономную трату стека. Ну и обрабатываться в итоге прерывание будет наиболее быстро.
как я и говорил, моя рекомендация наиболее эффективна, если эти функции более ниоткуда не вызываются. если они используются из нескольких мест, то со стеком не все так красиво...
вообще, совет определять все функции модуля, которые нужны только этому модулю, как static - вообще в практике AVR-программирования однозначно полезный совет.
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
это в применении к AVR практически всегда безусловно правильный совет. вы как-то совсем упускаете из виду, что главный ресурс AVR, который стоит беречь всеми силами, это ОЗУ. так вот, использование не-static функций в обработчике прерывания приводит к тому, что в стеке сохраняется слишком много регистров, а в случае с вызовом функций из других модулей или библиотечных, будут сохранены в стеке вообще все рабочие регистры. и кому это надо? а вот static-функции практически со 100% вероятностью будут проинлайнены и не смотря на количество передаваемых параметров обеспечат наиболее экономную трату стека. Ну и обрабатываться в итоге прерывание будет наиболее быстро.
как я и говорил, моя рекомендация наиболее эффективна, если эти функции более ниоткуда не вызываются. если они используются из нескольких мест, то со стеком не все так красиво...
Отчасти Вы правы, но:
I) Ради простоты, понятности, надежности.... исходного кода я с легкостью пойду на некоторые расходы (если надо перейду на MK c бОльшимми ресурсами). Например, вызов функции из стандартной библиотеки вместо static аналога, повышает понятность кода. Если не согласны - спорить не буду, но убедить в обратном меня практически невозможно ("опыт, сын ошибок трудных") 1) Разница в цене минимальна, например atmega48pa/atmega88pa (чип-дип: разница 6руб, для других поставщиков можете сами посмотреть) Если понятность и повторное использование кода, позволяет съекономить хотябы день разработчика, можно прикунуть, какой тираж нужен, чтобы окупить это. 2) более того, с учетом реалий, часто более старшую модель семейства можно купить даже дешевле (как более массовую).
II) Как я писал ранее, для меня важна простота, понятность, надежность, повторное использование исходного кода (минимизация времени программиста на разработку и сопровождение). А голова пусть у оптимизатора болит - у компьютера мегагерцев много. Оптимизатор опровергает Ваши доводы: Спойлер
Код:
/* static void* my_memset (void *b, int c, int s) { register char* p = (char*) b;
Да, использование стека, в случае локального static аналога memset () меньше, но совсем не так, как Вы предсказываете. Если я буду компилировать более свежей версией (сейчас gcc 4.5.3), не уверен, что эта разница вообще не уйдет на нет.
вообще, совет определять все функции модуля, которые нужны только этому модулю, как static - вообще в практике AVR-программирования однозначно полезный совет.
С этим вообще спорить бесполезно, так как полностью согласен. Но речь шла совсем про другое.
Качественное и безопасное устройство, работающее от аккумулятора, должно учитывать его физические и химические свойства, профили заряда и разряда, их изменение во времени и под влиянием различных условий, таких как температура и ток нагрузки. Мы расскажем о литий-ионных аккумуляторных батареях EVE и нескольких решениях от различных китайских компаний, рекомендуемых для разработок приложений с использованием этих АКБ. Представленные в статье китайские аналоги помогут заменить продукцию западных брендов с оптимизацией цены без потери качества.
PS. Провел лабораторную работу. Скомпилировал код от Пока_без_кота из этой ветки. Код не правил, добавил только несколько определений, чтобы компилировалось (warning-и не убирал) - файла AVR_caller.h у меня нету
Компилировал два варианта: 1) как есть 2) все функции (кроме main и обработчика - static)
Получил, то, что и ожидал. С включенной глобальной оптимизацией полученные бинарники (размер 324 байта) совпадают байт-в-байт. Без глобальной оптимизации: 1) размер 388 байт, в обработчике упрятывается в стек на 8 байт больше. 2) размер 324байта, бинарник байт-в-байт совпадает с теми, что собраны с глобальной оптимизацией
Вывод: static функции не влияют на оптимальность сгенерированного кода - оптимизатор все "подчистит".
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
теперь удаляем static из обоих модулей, делая все функции публично видимыми (обратите внимание, что во втором модуле пришлось локальной функции цифру приписать, чтобы конфликта имен не было). получаем следующее
а вот теперь делаем вывод, что больше влияет на результат: static или поведение оптимизатора
Добавлено after 8 minutes 20 seconds: заодно задумываемся о том, что будет, если модулей в проекте 20, и функций в них штук по 20, и параметров в функциях не по одному... но это уже факультативно
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
заодно задумываемся о том, что будет, если модулей в проекте 20, и функций в них штук по 20, и параметров в функциях не по одному... но это уже факультативно
Да нормально все там. И поболее проекты есть. Уже много лет пользуюсь. Никогда не делаю static функций только для оптимизации. Исключительно по назначению: чтобы ограничить "видимость". И уж никогда не буду дублировать код, если есть глобальная функция (проверенная и отлаженная), которая делает то, что надо - вызову ее (сообственно для этого она и глобальная - чтобы ее вызывать, когда надо )
Что такое "глобальная оптимизация"? я такого в упор не знаю...
хм... я думал, это всем, кто более-менее gcc пользует известно
Введено в районе версии 4.5 - сейчас точно не помню. Но в 4.5.3 точно есть. смотреть ключики -combine -fwhole-program В районе 4.6 версии (точно сейчас не помню - гуглить надо, да и неважно это), gcc-шники модернизировали эту "фичу", теперь она называется LTO (link time optimization) - принцип работы понятен из названия (оптимизация на этапе линковки, т.е. всего кода целиком).
вот именно - прочтите условия эксперимента, которые я описал.
LTO более-менее задышала совсем недавно (ну... как сказать, время летит...), и пока что лично я к этому еще не привык. А -combine -fwhole-program работает только в случае специально вручную созданного makefile или из командной строки, а я работаю из-под Eclipse, который компилирует файлы поотдельности и эту опцию не дает применять. И я уверен, что практически все тут собравшиеся поступают аналогично - все автоматом... так что, не смотря на то, что LTO и в самом деле дает какой-то эффект, лично я его никак не прочувствовал. но посмотрите: я получил ровно тот же результат без этой фичи, т.е. мой совет подходит для всех, а ваш - для приближающихся к просветлению...
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
ARV, как поступают все (или большинство) - мне неведомо, да и незачем мне это.
Сделать нужный Makefile: не считаю это "просветлением", обычное дело. Да и какой там Makefile - мэйкфайлик, ситаю всем кто собирает проекты - хотябы основы make знать надо. Намного жизнь облегчает.
Пока_без_кота, в чем вопрос? В том, что в соответствующем файле 7-ой бит регистра не определён? Он, вроде, SPI режим включает, если правильно помню. Так определите , если Вам нужно
Ну то что 7 бита нет, это одно, так еще и 6 бит не так называеться... По Вашей спокойной реакции, я так понимаю, такие плюхи сплошь и рядом, и на никто даже внимания не обращает ? Просто я компилирую, оно материться, я лезу в даташит, 10 раз перепроверяю, ишу ревизии даташита посвежее, убеждаюсь, что у меня самая последняя ревизия, читаю ерраты, ничего не нахожу, потом заглядываю в определения студии и офигеваю... Они просто взяли определения этого регистра от Тини2313 без А, а там иначе.
Ну то что 7 бита нет, это одно, так еще и 6 бит не так называеться... По Вашей спокойной реакции, я так понимаю, такие плюхи сплошь и рядом, и на никто даже внимания не обращает ? Просто я компилирую, оно материться, я лезу в даташит, 10 раз перепроверяю, ишу ревизии даташита посвежее, убеждаюсь, что у меня самая последняя ревизия, читаю ерраты, ничего не нахожу, потом заглядываю в определения студии и офигеваю... Они просто взяли определения этого регистра от Тини2313 без А, а там иначе.
А Вы думаете, avr libc боги пишут? беглый просмотр различий 2323a и 2323 показывает, что если откопировать iotn2313.h в iotn2313a.h (и поправить io.h), то исходник написанный для 2313 можно откомпилировать для 2313a и он будет работать в 2313А. Все - большинство пользователей удовлетворено. А некоторые различия потои можно поправить
ЗЫ В AVR C Runtime Library 2.0.0 поправлено: Спойлер
Ну во всяком случае приближенные к ним. Понял, теперь все время буду начеку. Возник еще вопрос. Для того, чтобы отправить SMS, надо отправить в модуль SIMCOM строку вида AT+CMGS="номер_телефона". Проблема в том, что компилятор ограничивает строки как раз такими же кавычками. Как это побороть ?
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 26
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения