parovoZZ Опубликовано 7 января, 2019 Поделиться Опубликовано 7 января, 2019 Есть у нас функция инициализации какого-то модуля или устройства, либо функция, которая просто возвращает значение регистра. Логичнее эти функции писать в файлах "драйверах", а не в main. Ну хотя бы с точки зрения переносимости кода между проектами. Но сразу появляется вопрос - что удобно программисту, то неудобно компилятору. Смысла в вызове однократно используемой функции или функции с одной командой нет - такие функции разумнее встроить в код. Но вот как быть - inline из другого *.c файла не вызывается, то бишь такую функцию надо писать в заголовке. Но такую функцию можно написать и как макрос (в том же заголовке - макрос в *.c файле тоже не виден али нет?). Так вот меня разрывает внутренняя устойчивая связь - как же поступить? 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
Alexeyslav Опубликовано 8 января, 2019 Поделиться Опубликовано 8 января, 2019 Вызывать функцию и не парится. 0 Учение - изучение правил. Опыт - изучение исключений. Ссылка на комментарий Поделиться на другие сайты Поделиться
20% скидка на весь каталог электронных компонентов в ТМ Электроникс!Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!Перейти на страницу акции Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849
ARV Опубликовано 9 января, 2019 Поделиться Опубликовано 9 января, 2019 В 1/8/2019 в 01:29, parovoZZ сказал: Есть у нас функция ..., которая просто возвращает значение регистра. Не надо делать таких функций. Все, что делается оператором присваивания, должно делаться оператором присваивания, функция тут - лишняя сущность. В остальном согласен с предыдущим оратором - оптимизаторы нынче умные пошли... многие "неудобности" проглатывают и не морщатся. 0 Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют... Ссылка на комментарий Поделиться на другие сайты Поделиться
Выбираем схему BMS для заряда литий-железофосфатных (LiFePO4) аккумуляторовОбязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей. Подробнее>>Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161
technik-1017 Опубликовано 9 января, 2019 Поделиться Опубликовано 9 января, 2019 Функция даст больше контроля над данными, чем макрос. Макрос лучше использовать там где с функцией не все получается так как надо. Я бы помог компилятору и всё же добавил бы inline. В возвращении функцией одного значения не вижу ничего плохого. 0 Наработки Ссылка на комментарий Поделиться на другие сайты Поделиться
Сравнительное тестирование аккумуляторов EVE Energy и Samsung типоразмера 18650Инженеры КОМПЭЛ провели сравнительное тестирование аккумуляторов EVE и Samsung популярного для бытовых и индустриальных применений типоразмера 18650. Для теста были выбраны аккумуляторы литий-никельмарганцевой системы: по два образца одного наименования каждого производителя – и протестированы на двух значениях тока разряда: 0,5 А и 2,5 А. Испытания проводились в нормальных условиях на электронной нагрузке EBD-USB от ZKEtech, а зарядка осуществлялась от лабораторного источника питания в режиме CC+CV в соответствии с рекомендациями в даташите на определенную модель. Подробнее>> Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161
ARV Опубликовано 9 января, 2019 Поделиться Опубликовано 9 января, 2019 (изменено) Только что, technik-1017 сказал: В возвращении функцией одного значения не вижу ничего плохого Главное, чтобы это было продиктовано какой-то необходимостью, а не сделано просто "ради красоты". Например, для атомарного доступа к многобайтным переменным или структурам, или для чего-то подобного. Если такой необходимости нет, то нет и принципиальной разницы между глобально видимой переменной и функцией для доступа к ней. И меньше раздумий о том, как лучше сделать Изменено 9 января, 2019 пользователем ARV 0 Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют... Ссылка на комментарий Поделиться на другие сайты Поделиться
Литиевые аккумуляторы EVE Energy и решения для управления перезаряжаемыми источниками тока (материалы вебинара)Опубликованы материалы вебинара Компэл, посвященного литиевым аккумуляторам EVE Energy и решениям для управления перезаряжаемыми источниками тока.На вебинаре мы представили информацию не только по линейкам аккумуляторной продукции EVE, но и по решениям для управления ею, что поможет рассмотреть эти ХИТ в качестве дополнительной альтернативы для уже выпускающихся изделий. Также рассмотрели нюансы работы с производителем и сервисы, предоставляемые Компэл по данной продукции. Подробнее>> Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161
Alexeyslav Опубликовано 9 января, 2019 Поделиться Опубликовано 9 января, 2019 Функция практически всегда лучше. Сейчас только один регистр, а потом появятся условия, код туда полезет... особено если эта функция - интерфейс будущей библиотеки. 0 Учение - изучение правил. Опыт - изучение исключений. Ссылка на комментарий Поделиться на другие сайты Поделиться
Литиевые батарейки и аккумуляторы от мирового лидера EVE в КомпэлКомпания Компэл, официальный дистрибьютор EVE Energy, бренда №1 по производству химических источников тока (ХИТ) в мире, предлагает продукцию EVE как со склада, так и под заказ. Компания EVE широко известна в странах Европы, Америки и Юго-Восточной Азии уже более 20 лет. Недавно EVE была объявлена поставщиком новых аккумуляторных элементов круглого формата для электрических моделей «нового класса» компании BMW.Продукция EVE предназначена для самого широкого спектра применений – от бытового до промышленного. Подробнее>> Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161
parovoZZ Опубликовано 10 января, 2019 Автор Поделиться Опубликовано 10 января, 2019 Ну вот пример. Есть такой цикл do { ADC_Change_in(ADC_channels[ADC_current_channel]); Sleep(SLEEP_MODE_ADC); Value_current[lsb][ADC_current_channel] = ADCL; Value_current[msb][ADC_current_channel] = ADCH; } while (ADC_current_channel--); Sleep () определена в этом же файле. В отдельном файле ADC.c определяю функцию: void ADC_Change_in (uint8_t Analog_input) { ADMUX = (1<<REFS1) | (0<<REFS0) | Analog_input; } И получаю размер кода 1232 байта. Комменчу эту функцию и вместо неё пишу в ADC.h: #define ADC_Change_in(Analog_input) ADMUX = (1<<REFS1) | (0<<REFS0) | (Analog_input) Размер кода 1164 байта! Компилятор AVR/GNU C Compiler : 5.4.0. Оптимизация O3. Смотрю дизасм - цикл развернут полностью (3 итерации), все функции заинлайнились. То бишь проверка условия цикла и вызов функций в данном случае получается накладнее, чем тупой линейный код. И, разумеется, мы выигрываем также и в скорости выполнения кода. 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
Alexeyslav Опубликовано 10 января, 2019 Поделиться Опубликовано 10 января, 2019 Выигрываем, конечно. Но какой ценой? А нужен ли этот выигрыш? 0 Учение - изучение правил. Опыт - изучение исключений. Ссылка на комментарий Поделиться на другие сайты Поделиться
technik-1017 Опубликовано 11 января, 2019 Поделиться Опубликовано 11 января, 2019 7 часов назад, parovoZZ сказал: Ну вот пример выложите минимальный проект для компиляции. у вас функция ADC_Change_in() не inline? 0 Наработки Ссылка на комментарий Поделиться на другие сайты Поделиться
ARV Опубликовано 11 января, 2019 Поделиться Опубликовано 11 января, 2019 (изменено) Вставлю своё скромное мнение. 1. 10 часов назад, parovoZZ сказал: Sleep () определена в этом же файле То есть "сон" у вас логически увязан с текущим модулем каких-то измерений, а переключение каналов измерительных логически не увязано и находится в другом файле. Я верно понял? 2. void ADC_Change_in (uint8_t Analog_input) { ADMUX = (1<<REFS1) | (0<<REFS0) | Analog_input; } Правила хорошего тона потребуют от вас изменить функцию как-то так: void ADC_Change_in (uint8_t Analog_input) { if(Analog_input < VALID_AIN) ADMUX = (1<<REFS1) | (0<<REFS0) | (Analog_input); } А это уже в макрос хуже ложится. А там, глядишь, и еще что-то понадробится добавлять... Как итог: не лучше ли пересмотреть логику создания модулей программы так, чтобы все нужные функции оказались в нужных файлах? Тогда не надо будет ничего мудрить, а инлайн возьмет на себя компилятор - он очень хорошо инлайнит однократно вызываемые static-функции. В качестве полукостыльного решения вашей проблемы порекомендую попробовать опцию компилятора/линкера -flto, которая вполне может проинлайнить и функции из других модулей... Изменено 11 января, 2019 пользователем ARV 0 Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют... Ссылка на комментарий Поделиться на другие сайты Поделиться
parovoZZ Опубликовано 11 января, 2019 Автор Поделиться Опубликовано 11 января, 2019 4 часа назад, technik-1017 сказал: у вас функция ADC_Change_in() не inline? Она определена в отдельном с файле. Поэтому что static, что inline, extern - компилятор её не сможет заинлайнить. Чтобы это случилось, её надо определить в заголовке, ну или в вызывающем файле. Первое меня устраивает, но возникает вопрос данного топика, второе меня категорически не устраивает). 31 минуту назад, ARV сказал: То есть "сон" у вас логически увязан с текущим модулем каких-то измерений, а переключение каналов измерительных логически не увязано и находится в другом файле. Я верно понял? Не совсем понял вопроса. Но отвечу. Данный цикл вызывается по сработке от таймера, чтобы обеспечить равномерную по времени оцифровку. АЦП включен в режиме свободного запуска. Я меняю канал мультиплексора и увожу ЦПУ в ADC Noise Reduction. Как только ЦПУ остановится, автоматически запустится АЦП на измерение. По окончании я выхожу из сна через обработчик прерывания от АЦП и снимаю показания. И так три раза. 37 минут назад, ARV сказал: Правила хорошего тона потребуют от вас изменить функцию как-то так: Когда над проектом работает несколько человек - да, несомненно. У меня же каналы определяются через #define (тупо числа из даташита) и они же заносятся в массив для возможности перебора. Если есть более изящное решение по переключению каналов, то извольте выложить=) 11 час назад, Alexeyslav сказал: Выигрываем, конечно. Но какой ценой? А чем я плачу? Размер кода уменьшен, скорость выполнения выше. 41 минуту назад, ARV сказал: В качестве полукостыльного решения вашей проблемы порекомендую попробовать опцию компилятора/линкера -flto, которая вполне может проинлайнить и функции из других модулей... Спасибо, почитаю. 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
ARV Опубликовано 11 января, 2019 Поделиться Опубликовано 11 января, 2019 (изменено) Только что, parovoZZ сказал: Не совсем понял вопроса Если вы переключение каналов поместите в тот же файл, где и sleep() и замеры, проблема исчезнет. Я об этом. Разбиение проекта на модули может быть по 2 основным принципам: по функционалу и по логике. По функционалу все, что касается АЦП, должно быть в одном файле-модуле, и в этом случае не понятно, с чего ИЗМЕРЕНИЕ ПРИ ПОМОЩИ АЦП у вас в одном файле, а ПЕРЕКЛЮЧЕНИЕ КАНАЛОВ АЦП в другом. Если по функционалу, то тоже все просится в один файл (включая таймерное прерывание), интерфейсом к которому будет массив готовых измеренных значений или функция для доступа к этому массиву. Только что, parovoZZ сказал: её надо определить в заголовке В заголовке определять функцию - дурной тон, не надо так делать. Только что, parovoZZ сказал: второе меня категорически не устраивает Вот я и вопрошаю: почему? Изменено 11 января, 2019 пользователем ARV 0 Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют... Ссылка на комментарий Поделиться на другие сайты Поделиться
parovoZZ Опубликовано 11 января, 2019 Автор Поделиться Опубликовано 11 января, 2019 30 минут назад, ARV сказал: Вот я и вопрошаю: почему? Удобнее переносить файлы между проектами. Можно и одной страницей писать ( как это делают поклонники ардуины) - это даже удобнее при изучении исходников. 31 минуту назад, ARV сказал: в этом случае не понятно, с чего ИЗМЕРЕНИЕ ПРИ ПОМОЩИ АЦП у вас в одном файле, а ПЕРЕКЛЮЧЕНИЕ КАНАЛОВ АЦП в другом. Потом через макросы унесу в ADC.h 1 час назад, ARV сказал: А это уже в макрос хуже ложится. через do { }while(0); должно залезть=) 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
ARV Опубликовано 11 января, 2019 Поделиться Опубликовано 11 января, 2019 (изменено) Вы не совсем правильно понимаете мою мысль... ну или я не могу её донести до вас понятным образом. Попробую еще раз. Есть подход разбиения проекта на модули по периферии: adc - все, что касается АЦП, timer - все, что касается таймера, usart - все что касается USART и т.д. При этом почти всегда происходит то, что у вас: функция в одном модуле, а используется в другом, что порождает накладные расходы. Есть подход разбиения проекта на модули по ЛОГИКЕ АЛГОРИТМА: measure - все, что касается измерения (АЦП, таймер, который запускает АЦП, промежуточные буферы и т.п.), calculate - все, что касается бизнес-логики проекта (обработка измеренных значений, вычисление управляющих воздействий и т.п.) и так далее. Примеры надуманные, но должно быть ясно, в чем суть. При этом вопросов, аналогичных вами описанным, не возникает в принципе. Хотя нет гарантии, что не возникнут другие вопросы Изменено 11 января, 2019 пользователем ARV 0 Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют... Ссылка на комментарий Поделиться на другие сайты Поделиться
parovoZZ Опубликовано 11 января, 2019 Автор Поделиться Опубликовано 11 января, 2019 Ну почему же? Понял. Я так и делаю. И именно из-за желания заинлайнить короткие и однократно вызываемые функции и возникла эта тема. 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
ARV Опубликовано 11 января, 2019 Поделиться Опубликовано 11 января, 2019 Значит, показалось Современный компилятор, в частности, GCC, без всяких макросов прекрасно инлайнит короткие функции внутри одного модуля, а с LTO-оптимизацией может попробовать и межмодульно... 0 Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют... Ссылка на комментарий Поделиться на другие сайты Поделиться
DrobyshevAlex Опубликовано 11 января, 2019 Поделиться Опубликовано 11 января, 2019 2 часа назад, ARV сказал: Есть подход разбиения проекта на модули по периферии: adc - все, что касается АЦП, timer - все, что касается таймера, usart - все что касается USART и т.д. Вот как раз сейчас делая проект для себя небольшой, на стм32, столкнулся с проблемой как логичней сделать. Хотелось бы отсебятины добавить. Например куб делает так, он создает функцию TIM_init, GPIO_init То есть в TIM все что касается регистров TIM а в GPIO что касается гпио Но это оказалось очень не удобным! Например мне надо настроить ногу для таймера, почему она должна настраиваться в GPIO если логичней это отнести к настройке таймера? Возможно это дело привычки. То есть я выношу в отдельный файл все что касается получения температуры, а это вариант с DMA+TIMER или просто в цикле опрос. И вот тут выходит не логично хранить настройку ноги в функции GPIO 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
parovoZZ Опубликовано 11 января, 2019 Автор Поделиться Опубликовано 11 января, 2019 4 минуты назад, ARV сказал: а с LTO-оптимизацией может попробовать и межмодульно... но ему ж тогда придется функцию с квалификатором inline компилировать в отдельный модуль? 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
ARV Опубликовано 11 января, 2019 Поделиться Опубликовано 11 января, 2019 (изменено) Я говорил о ситуациях без квалификаторов inline - вроде как и без этого все может быть сделано... Тем более что inline само по себе не гарантирует встраивание... Только что, DrobyshevAlex сказал: То есть я выношу в отдельный файл все что касается получения температуры, а это вариант с DMA+TIMER или просто в цикле опрос. И вот тут выходит не логично хранить настройку ноги в функции GPIO Бинго! О чем я и говорил. Я для себя применяю следующий способ, снимающий практически любой головняк в подобных случаях. GCC имеет встроенные секции кода init0...init9, в которых можно размещать naked-функции, которые будут "вызваны" автоматически при компиляции ДО начала main. В каждом модуле я делаю такую функцию в секции с номером 6-8 (9 - это фактически main, а первые секции могут быть с еще не инициализированным стеком или не обнуленными/не проинициализированными static-переменными), где инициализирую всю периферию и т.п., необходимую для ЭТОГО модуля. В main при этом никаких init_xxxx() вообще не требуется. Мне такой подход представляется очень удобным... хотя есть и критики. Изменено 11 января, 2019 пользователем ARV 0 Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют... Ссылка на комментарий Поделиться на другие сайты Поделиться
parovoZZ Опубликовано 11 января, 2019 Автор Поделиться Опубликовано 11 января, 2019 3 часа назад, ARV сказал: В заголовке определять функцию - дурной тон, не надо так делать. В заголовках атмела определения inline функций заменены на макросы. Значит, тема раскрыта. 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
ARV Опубликовано 11 января, 2019 Поделиться Опубликовано 11 января, 2019 Это не отменяет дурного тона 0 Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют... Ссылка на комментарий Поделиться на другие сайты Поделиться
Alexeyslav Опубликовано 11 января, 2019 Поделиться Опубликовано 11 января, 2019 А почему вы не можете конфигурировать GPIO относящиеся к таймеру в модуле инициализации таймера? Главное лишнего там не трогать, а в модуле инициализации GPIO - исключительно ноги которые используются как GPIO и не трогать ноги относящиеся к таймеру? Если для GPIO необходимо указывать тайминги, рабочую частоту - то можно это сделать в модуле GPIO а в модуле таймера выставить лишь необходимый режим работы ноги для таймера. При этом важно инициализацию GPIO произвести до таймера. И никакая логика не страдает. 0 Учение - изучение правил. Опыт - изучение исключений. Ссылка на комментарий Поделиться на другие сайты Поделиться
parovoZZ Опубликовано 12 января, 2019 Автор Поделиться Опубликовано 12 января, 2019 11 час назад, ARV сказал: Это не отменяет дурного тона Просматриваю сейчас библиотеку LUFA - вообще не стесняются определения функции в заголовке )) 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
ARV Опубликовано 12 января, 2019 Поделиться Опубликовано 12 января, 2019 Просмотрите исходник avr-libc или ядра linux - там goto и longjmp сплошняком... и тем не менее общепринято считать это дурным стилем программирования. Никто не расстреливает за это, но и в восторг не приходит. Просто имейте ввиду. 0 Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют... Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения
Присоединяйтесь к обсуждению
Вы публикуете как гость. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.