Обсуждаем контроллеры компании Atmel.
Ответить

Re: WinAvr в вопросах и ответах

Ср ноя 25, 2020 23:58:06

Спасибо за ответ.
если никаких других "переменных" в EEPROM у вас в проекте нет, то да, массив будет с нулевого адреса помещен, а если есть и другие - то не факт.

Да, в том-то и дело, что уже есть пара значений, которые при необходимости пишутся в первые ячейки, поэтому и хотелось размещать предустановленные данные не с нулевого адреса, а немного отступив от начала.
не советую с этим заморачиваться вообще.

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

Upd. Насколько я понял, нужно в Makefile в параметрах линкера определить новую секцию, используя
Код:
--section-start=.my_section=0x81xxxx

где 0x81 указывает на расположение секции в EEPROM, а xxxx - её начальный адрес.
Затем в самом коде указываем что-нибудь типа
Код:
__attribute__((section(".my_section"))) uint8_t my_array[64]={ ... };

после чего при компиляции создастся файл .eep.

Re: WinAvr в вопросах и ответах

Чт ноя 26, 2020 08:04:46

Andrew88 писал(а):Да, в том-то и дело, что уже есть пара значений, которые при необходимости пишутся в первые ячейки, поэтому и хотелось размещать предустановленные данные не с нулевого адреса, а немного отступив от начала.
еще раз: вам не надо заботиться об адресах размещения данных в памяти, это за вас сделают компилятор и линкер, и "немного отступив" не потребуется, все и так не будет накладываться.

Re: WinAvr в вопросах и ответах

Чт ноя 26, 2020 10:50:09

Да, в том-то и дело, что уже есть пара значений, которые при необходимости пишутся в первые ячейки, поэтому и хотелось размещать предустановленные данные не с нулевого адреса, а немного отступив от начала.

Я так понимаю "пара значений" пишется напрямую через функции eeprom_write_* или регистры сразу? Так сделайте их тоже EEMEM и пишите через eeprom_write_* / eeprom_update_* по адресам указателей EEMEM. Так компилятор сам раскидает всё как надо и не придется заморачиваться с доп. секцией.
В общем случае лучше не смешивать доступ по адресам EEMEM указателей и свою прямую адресацию. Уж что-то одно использовать надо, чтобы не возникло "наложения".

Re:

Чт янв 06, 2022 08:57:34

рекомендаций много :)

extern далеко не всегда помогает уменьшить объем кода, скорее наоборот, а вот static может сильно помочь (если вы, конечно, понимаете, что это и как оно работает). вы запрещаете инлайнить функции - но зачем? поверьте, компилятор лучше вас разберется, когда это выгодно делать, а когда нет: запрещая инлайнить небольшую функцию вы заставляете компилятор каждый раз при ее вызове спасать в стеке несколько регистров, инициализировать ее локальные переменные и т.д. - а если она проинлайнится, то все это скорее всего будет лишним, и еще вопрос, станет ли код больше...

если вы программируете не очень аккуратно и у вас имеются функции, которые просто "для запаса" содержатся в тексте - они будут включены в код, хотя по сути лишние. так вот, убрать их можно опцией компилятора -ffunction-sections и опцией линкера -Wl,-gc-sections - для "мусорного кода" очень большой эффект!

вчера из проекта с кодом в 2038 байт сумел сделать 1930 байт путем замены некоторых статических глобальных переменных на регистровые.

WinAVR не может похвастаться сверхоптимальным кодом для работы с битовыми полями, особенно когда эти поля знаковые или многобитные. но если структура с битовыми полями умещается в регистре или паре регистров, то сделав ее регистровой переменной вы получите заметный выигрыш. часто можно отказаться от однобитовых полей, заменив их отдельными байтовыми переменными или полями в структуре - если ОЗУ хватает, то скорее всего получите выигрыш в размере кода.

используйте для функции main() атрибут OS_main. помните о том, что если вы описываете статическую или глобальную переменную и сразу инициализируете ее ненулевым значением, то это самое значение приплюсуется к коду. подумайте, действительно необходимо это делать или можно обойтись нулевым значением по умолчанию.

посмотрите, реально ли необходимо иметь в функциях более одного параметра? действительно ли необходимы типы int и long? можно ли обойтись uint8_t или нет? не используйте float и double - для проектов на tiny ничего хорошего не выйдет скорее всего из этой попытки...

есть и еще тонкости, которые все я не помню, хотя дома записано многое :)


поделитесь, пожалуйста, своими записями и наработками

Re: WinAvr в вопросах и ответах

Чт янв 06, 2022 10:55:13

Что конкретно интересует?

Re: WinAvr в вопросах и ответах

Чт янв 06, 2022 10:58:58

интересуют ваши лайфхаки, наработки, заметки по компилятору для WinAVR
тоесть информация такого вида как я привел в посте выше

Re: WinAvr в вопросах и ответах

Чт янв 06, 2022 12:03:16

вы решили заняться экстремальным программированием на AVR? ;)
последние годы я озабочен не размером итогового кода, а тем, насколько красиво и просто решаются мои задачи, поэтому все эти лайфхаки постепенно теряются за неактуальностью.

кое-что вспомнить могу.

для проектов, состоящих из множества исходников, можно поэкспериментировать с опцией -flto (использовать и при компиляции, и при линковке). иногда это даёт очень хороший эффект, правда, эффект этот разный от версии к версии avr-gcc

в дополнение к ранее описанной опции -ffunction-sections можно применять и -fdata-sections, при не очень аккуратном кодинге позволит избавиться от незадействованных (но описанных в коде) переменных, т.е. позволит сэкономить ОЗУ

в качестве универсального совета по "тюнингу" кода могу рекомендовать чтение раздела из документации avr-gcc, посвященной опциям оптимизации. там описаны все флаги-переключатели и их эффекты. стандартные опции -Ox по сути являются упрощенным вариантом одновременного включения-отключения множества отдельных флагов оптимизатора (в документации они перечислены). так вот, не всегда стандартный набор этих флагов для режима -Os будет давать минимальный объем прошивки. можно, читая документацию, пробовать в включать "нестандартные" для этого режима флаги, или отключать "стандартные". комбинаций - миллиард, но иной раз удаётся подобрать наиболее удачную...

ну например, по умолчанию -Os отключает "разворачивание" циклов, т.е. "невидимо" устанавливает опцию -fno-unroll-loops. это даёт хороший результат для "длинных" циклов, но итоговый код для, например, обнуления 2 или 3 байтов подряд будет больше, чем если бы этой опции не было. если в вашем коде много циклов с малым количеством итераций, а их тело состоит из одного-двух операторов, есть вероятность, что без этого флага код будет меньше. поэтому в дополнение к -Os вы просто добавляете -funroll-loops (т.е. без no-), и смотрите на результат.

-f - это опция изменения состояния флага компилятора, за ним без пробела следует наименование устанавливаемого флага. если же флаг нужно сбросить, перед его наименованием нужно добавить no-. количество таких установок одного и того же флага может быть сколько угодно большим, но действовать будет самая последняя. т.е. в случае -fno-unroll-loops -funroll-loops будет включен флаг "разворачивания циклов".

для моих проектов наибольший эффект давали именно опции управления циклами, инлайнингом функций (и для циклов и для функций там есть флаги, устанавливающие "вес" для срабатывания опции, так вот, меняя этот вес можно добиваться минимума размера прошивки), а так же опции, управляющие поведением целочисленных вычислений. есть там флаг (к сожалению, подзабыл, как он называется), управляющий тем, чтобы числа int и long помещались при вычислениях в регистры, следующие "подряд" (пересказываю по памяти, и могу несколько исказить истину). так вот, включение этой опции для "маломерных" МК иной раз позволяет впихнуть невпихуемое...

последние версии avr-gcc сильно отличаются от той версии, для которой я писал процитированное вами... и я не уверен, что советы будут актуальными для свежатинки.

из "лайфхаков", позволяющих упростить собственно кодинг (не выиграть в размере, а выиграть в красоте и понятности исходника, что лично для меня стало более важным), порекомендую обратить взгляд на новые "префиксы" для "переменных" в flash-памяти (то есть констант, находящихся в памяти программ) __flash и __xmem (появились с версии avr-gcc 4.x.x). с их помощью можно избавиться от функций pgm_read_xxxx и работать с такими переменными и массивами напрямую через указатели, как и для обычного ОЗУ.

поскольку я работаю в Eclipse, который не может корректно распарсить "переменные" с такими префиксами, и поэтому не подсвечивает их (в т.ч. помечает эти строки "некорректными" при автоконтроле синтаксиса), то для Eclipse есть отдельный лайфхак, устраняющий ту проблему.
надо зайти в настройки проекта Preprocessor Include Paths, Macros etc:
Изображение
и там в разделе CDT User Setting Entries добавить определение пустого макроса __flash __xmem, если нужно):
Изображение
поле этого парсер Eclipse будет думать, что __flash это макрос, а компилятор так думать не будет :)))

ну, вот как-то так...

если будут конкретные вопросы - постараюсь ответить. а вот так, абстрактно "о своих наработках" спрашивать не надо, т.к. я не понимаю, о чем говорить...
Вложения
eclipse-2.JPG
(24.14 KiB) Скачиваний: 596
eclipse-1.JPG
(96.58 KiB) Скачиваний: 600

Re: WinAvr в вопросах и ответах

Пт янв 07, 2022 13:12:41

ARV, не совсем по теме. Я как то смотрел ваш плейер световых эффектов... Заради чего все эти извращения с компоновщиком?

Re: WinAvr в вопросах и ответах

Пт янв 07, 2022 14:56:57

OKF писал(а):Заради чего все эти извращения с компоновщиком?
основной мотив моих телодвижений - упростить процесс разработки для себя любимого. :)
например, где обычно делают инициализацию периферии и/или локальных переменных? как правило, это делают в некоей init-функции, вызываемой в числе первых из main. я же уже лет 10, пожалуй, делаю это в секции .init7 (или других аналогичных), помещая нужный код в каждом модуле по мере необходимости. поэтому у меня, например, вполне рабочий такой код:
Код:
#include <avr/io.h>
#include "com_io.h"

int main(void){
  printf("Hello world!");
}
то есть в main - только то, что в main нужно делать, а остальное - там, где оно логично.

точно по той же причине я сделал "изврат" с линкером. поясняю.

можно ли в Си создать массив функций? да.
можно ли описать эти функции в 100 отдельных исходных файлах? да
удобно ли это в работе? нет
почему это не удобно? да потому, что в Си нужно собрать объявления всех функций в заголовочном файле, чтобы потом поместить их (вручную!) в инициализацию массива. когда в процессе разработки появляются новые идеи, такая "ручная" работа становится утомительной.

вот я и придумал, как при помощи управления секциями линкера сделать автоматическую инициализацию массива некими константами, разбросанными по всем исходникам. только и всего.

в частности, если мне захочется пополнить мой плейер поддержкой новой команды, мне нужно будет:
1. создать новый исходник, где реализовать обработчик этой команды (при помощи макроса, помещающего этот обработчик в нужную секцию)
2. всё.
ни один другой исходник или заголовочный файл корректировки не потребует.

разве это не удобно?

Re: WinAvr в вопросах и ответах

Пт янв 07, 2022 16:55:41

Ну да, наверняка это удобно. Для вас. В данном конкретном случае. А как это вписывается в совместимость c другими компиляторами? В чём тогда фишка Си? Я пишу на высокоуровневом языке для чего? Для того что бы переносить код на другие платформы и архитектуры, верно? На кой же мне ещё изгаляться с фишками каждого конкретного линкера? Заради того, что вам чуть-чуть удобнее? Как то это странненько, согласитесь?

Re: WinAvr в вопросах и ответах

Пт янв 07, 2022 18:29:04

OKF писал(а):Как то это странненько, согласитесь?
да не странненько... переносимость программ на Си - это миф. я о том, что ни одна программа, за исключением хелловордов, не может быть перенесена на другую платформу без корректировки исходников. между компиляторами чуть получше, но все равно переносимость обеспечивается весьма слабо, приходится городить кучу всяких директив условной компиляции...

что касается конкретно моего подхода, то в семействе компиляторов GCC принципы работы компилятора и линкера одинаковы, поэтому код получается весьма неплохо переносимым для этого семейства компиляторов, что было доказано путем сборки моего плейера под платформу ARM. в других компиляторах, вероятно, вместо секций используется что-то аналогичное, соответственно, подход останется применимым... но, поскольку я не работаю ни с чем, кроме GCC, заранее внедрить в мои макросы соответствующие "нюансы" я не могу (и не хочу).

Re: WinAvr в вопросах и ответах

Пт янв 07, 2022 18:36:08

Да ни какой не миф! На кой тогда он нужен этот Си - высокоуровневый язык? Придерживайтесь правил, отделяйте физику от логики, всего то! Неуж то мне вам это нужно объяснять? Это ж как отче наш должно быть!

Re: WinAvr в вопросах и ответах

Пт янв 07, 2022 18:41:22

OKF писал(а):Придерживайтесь правил, отделяйте физику от логики, всего то!
ну так у меня все так и есть! логика в макросах, а макросы можно править под платформу/компилятор. скрипт линкера тоже. или вы хотите сказать, что, например, под ARM без работы со скриптом линкера можно что-то "портабельное" собрать запросто? вот и вся ваша переносимость...

я ж вас не заставляю пользоваться моими приёмами! хотите обеспечивать мнимую переносимость - корячьтесь с ручной правкой кучи файлов и массивов, я ж не против. а мне на аспект переносимости плевать, поскольку я работаю для себя любимого :)))

Re: WinAvr в вопросах и ответах

Пт янв 07, 2022 18:46:25

Ага. Вот и получается что с вашими "приёмами" людям приходится не только с логикой разбираться, но ещё и с вашими линкерскими выебонами, не так ли? Ну да, конечно, вы крут! Офигенно крут! А-ха-ха! Бурные, ннесмолкающие, аплодисменты... Ужос!

Re: WinAvr в вопросах и ответах

Пт янв 07, 2022 19:01:48

OKF писал(а):людям приходится не только с логикой разбираться, но ещё и с вашими линкерскими выебонами
ну, если вы работаете с ARM-ами, вы тоже должны со скриптами линкера ковыряться... и не только с ними! вы так же возмущены нехорошим поведением разработчиков софта под ARM?

не понимаю вашего неистовства... ну не нравится - и не применяйте. чего кипятиться-то?

Re: WinAvr в вопросах и ответах

Пт янв 07, 2022 19:08:06

Нет. Вы вправе делать так, как вам соизволится, какие тут могут быть претензии.
Просто, если вы хотите доносить своё творение в массы, то должны всё же упрощать этот процесс.
Моё мнение. Удачи!

Re: WinAvr в вопросах и ответах

Пт янв 07, 2022 20:00:46

OKF писал(а):если вы хотите доносить своё творение в массы, то должны всё же упрощать этот процесс
так куда еще упрощать: все проекты, которые я "выношу в массы" имеют готовый makefile для сборки проекта? то есть приняв мою концепцию программирования, вы можете править все исходники по-своему, а потом собрать из них результат! и ковыряться в скрипте линкера вам не потребуется.

чего еще вам не хватает? портировать мой проект для atmega328 на PIC16 все равно не получится, как ни лезь из кожи вон :)))

Re: WinAvr в вопросах и ответах

Пт янв 07, 2022 20:09:06

А как это вписывается в совместимость c другими компиляторами? В чём тогда фишка Си?

На кой тогда он нужен этот Си - высокоуровневый язык?

Просто, если вы хотите доносить своё творение в массы, то должны всё же упрощать этот процесс.

Если ты великовозрастный дебил, не надо напрягать своей проблемой других.

Re: WinAvr в вопросах и ответах

Пн янв 10, 2022 18:34:58

winavr - ошибка компиляции no rule to make target "***.elf"
подскажите ,как исправить?

Добавлено after 3 hours 34 minutes 7 seconds:
winavr - ошибка компиляции no rule to make target "***.elf"
подскажите ,как исправить?


Вроде разобрался,библиотеки с плагинами нужны.

Re: WinAvr в вопросах и ответах

Пн янв 10, 2022 20:07:29

... портировать мой проект для atmega328 на PIC16 все равно не получится, как ни лезь из кожи вон :)))

Вот и я об этом. А писали бы "как люди", так и портировалось бы.)
Ответить