|
|
  |
Прописывание версии ПО (прошивки) |
|
|
|
Sep 10 2015, 12:37
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 3-09-11
Из: Минск
Пользователь №: 66 982

|
Цитата(Сергей Борщ @ Sep 9 2015, 15:00)  И тем самым отключить выбрасывание всех неиспользуемых переменных. Если бы у меня возникла необходимость оставить в памяти неиспользуемую константу, я бы поместил ее в отдельную секцию (__attribute__((section("имя_секции")))) и разместил бы эту секцию именно туда, где она мне нужна, запретив линкеру ее выкидывать ( KEEP(*(имя_секции)) ) Что то не получается у меня реализовать ваш пример. Где я ошибся??? Код const char name_fw[5] PROGMEM = "xxxx"; __attribute__ ((section (".init3"))); KEEP(*(".init3"));
|
|
|
|
|
Sep 10 2015, 13:47
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 3-09-11
Из: Минск
Пользователь №: 66 982

|
Цитата(demiurg_spb @ Sep 10 2015, 15:55)  Вы собственно не применили атрибут. Код const char __attribute__ ((section (".init3"))) name_fw[5] = "xxxx"; KEEP(*(".init3")); Теперь ругается на звездочку: expected declaration specifiers or '...' before '*' token
|
|
|
|
|
Sep 10 2015, 14:00
|
Знающий
   
Группа: Свой
Сообщений: 526
Регистрация: 24-08-07
Из: Беларусь, Минск
Пользователь №: 30 045

|
Цитата(demiurg_spb @ Sep 9 2015, 16:38)  Цитата(Spider @ Sep 9 2015, 16:04)  Раз уж такая пьянка, а не расскажете как заставить make пересобирать конкретный *.c даже если в нём не было изменений? Встречный вопрос: зачем? Например что бы обновлялась версия/дата сборки при каждой пересборке. Делается это так: Код .PHONY: FORCE FORCE:
timestamp.o: FORCE
%.o: %.c $(CC) ...
|
|
|
|
|
Sep 10 2015, 19:05
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Twin_by @ Sep 10 2015, 16:47)  Теперь ругается на звездочку: expected declaration specifiers or '...' before '*' token Так строку KEEP(*(".init3")) надо в скрипт лнкера вписывать, чтобы он знал, в какое именно место памяти надо вашу строку разместить. И не стоит использовать секции .initX - они уже используются стартапом. Цитата(Spider @ Sep 9 2015, 16:04)  а не расскажете как заставить make пересобирать конкретный *.c даже если в нём не было изменений? touch my_file.c & make Чаще всего такая необходимость возникает при смене каких-то ключей в makefile. А поскольку мы заранее не знаем, какие файлы это может затронуть, лучше заставить make пересобирать все файлы при изменении makefile. У меня список всех объектных файлов собирается в переменной OBJ, поэтому в makefile присутствует строка: Код $(OBJ): makefile
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 11 2015, 06:43
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 3-09-11
Из: Минск
Пользователь №: 66 982

|
Цитата(Сергей Борщ @ Sep 10 2015, 22:05)  Так строку KEEP(*(".init3")) надо в скрипт лнкера вписывать, чтобы он знал, в какое именно место памяти надо вашу строку разместить. И не стоит использовать секции .initX - они уже используются стартапом. А какую секцию лучше использовать? Я кроме этих секций AVR GCC: секции памяти (что такое .text, .data, .bss, .noinit?) , других не знаю. И второй вопрос где и как отредактировать скрипт линкера или где можно прочитать про него? Так чтобы на доступном языке. Я с этими вещами первый раз столкнулся поэтому опыта в этом маловато.
|
|
|
|
|
Sep 11 2015, 07:16
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Twin_by @ Sep 11 2015, 09:43)  А какую секцию лучше использовать? Я кроме этих секций AVR GCC: секции памяти (что такое .text, .data, .bss, .noinit?) , других не знаю. Пока вы глубоко в этом не разобрались, добавлять можно в .text. Добавлять в .data не очень хорошо - вы получите копию вашей строки в ОЗУ. .bss, .noinit - тоже ОЗУ, но в отличие от .data их содержимое вообще в прошивку не попадает. Цитата(Twin_by @ Sep 11 2015, 09:43)  И второй вопрос где и как отредактировать скрипт линкера Поищите в комплекте вашего компилятора файлы с расширением .ld Посмотрите их содержимое, почитайте комментарии в них. выберите тот, который подходит к вашему процессору (можно было каким-то ключем линкера узнать, какой из них он использует по-умолчанию для вашего процессора, но я не помню какой именно ключ нужен. Вы можете найти его самостоятельно, почитав документацию на линкер Google->"gnu ld"). Копируйте выбранный файл в папку проекта, дайте ему внятное имя и укажите линкеру использовать этот файл (в командную строку линкера добавьте -Wl,-T,имя_файла_скрипта). Цитата(Twin_by @ Sep 11 2015, 09:43)  или где можно прочитать про него? Так чтобы на доступном языке. Не знаю, насколько доступен для вас английский. По ссылке выше в документации на линкер это раздел "3 Linker Scripts". Можете поискать перевод.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 11 2015, 13:05
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 3-09-11
Из: Минск
Пользователь №: 66 982

|
Цитата(Сергей Борщ @ Sep 11 2015, 10:16)  Поищите в комплекте вашего компилятора файлы с расширением .ld Посмотрите их содержимое, почитайте комментарии в них. выберите тот, который подходит к вашему процессору (можно было каким-то ключем линкера узнать, какой из них он использует по-умолчанию для вашего процессора, но я не помню какой именно ключ нужен. Вы можете найти его самостоятельно, почитав документацию на линкер Google->"gnu ld"). Копируйте выбранный файл в папку проекта, дайте ему внятное имя и укажите линкеру использовать этот файл (в командную строку линкера добавьте -Wl,-T,имя_файла_скрипта). Что удалось узнать пока. Файлы ld Atmel Studio как таковые не использует. Она использует файлы в папке c:\WinAVR-20100110\avr\lib\ldscripts\avr2.* (avr2.* имеет поддержку процессора Attiny88 http://microsin.net/programming/avr/avr-gcc-options.html ) имеющие следующие описание: *.x script file is the default script *.xr script is for linking without relocation (-r flag) *.xu script is like .xr but *do* create constructors (-Ur flag) *.xn script is for linking with -n flag (mix text and data on same page). *.xbn script is for linking with -N flag (mix text and data on same page). Why are there five different linker scripts?Вот тут даются рекомендации по использованию своего скрипта AVR Libc Reference Manual Controlling the linker avr-ld. Там они предлагают заменить стандартный avr2.x на свой. Что я потом сделал. Я скопировал файл avr2.x в папку с проектом (там где Makefile, *.o, *.d), переименовал его в version_fw.x. Отредактировал его содержимое, добавив Код *(.text) KEEP(*(.text)) строчка 75 Потом в Atmel Studio main Properties -> Toolchain -> AVR/GNU Linker/Miscellaneous прописал -Wl,-T,-version_fw.x (или -version_fw). И при компилирование снова выдал ошибку: expected declaration specifiers or '...' before '*' token Прикрепил файл, расширение сменить на *.x
|
|
|
|
|
Sep 11 2015, 13:32
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Twin_by @ Sep 11 2015, 16:05)  Код *(.text) KEEP(*(.text)) Тут имя секции .text не подходит. При линковке есть понятие "входные секции" - это которые компилятор создает в объектных файлах из вашего исходника и "выходные секции" - это в которые линкер складывает входные секции. То есть линкер берет входные секции и размещает их в выходные согласно скрипта. В выходном файле входных секций уже нет, в нем только выходные. Вы правильно разместили свою секцию внутри выходной секции .text. Но имя вашей секции надо было дать какое-то другое. Имя .text компилятор использует для кода. Цитата(Twin_by @ Sep 11 2015, 16:05)  Потом в Atmel Studio main Properties -> Toolchain -> AVR/GNU Linker/Miscellaneous прописал -Wl,-T,-version_fw.x (или -version_fw). Минус лишний перед именем скрипта:-Wl,-T,version_fw.x Цитата(Twin_by @ Sep 11 2015, 16:05)  И при компилирование снова выдал ошибку: expected declaration specifiers or '...' before '*' token А вы строчку KEEP(*(".init3")) из исходника убрали? Попробуйте так: В исходнике Код __attribute__ ((section (".fw_version"))) const char name_fw[] = "xxxx"; В скрипте линкера: Код *(.text) /*тут где-то еще должно быть*/ *(.text.*) KEEP(*(.fw_version))
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 11 2015, 14:03
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 3-09-11
Из: Минск
Пользователь №: 66 982

|
Цитата(Сергей Борщ @ Sep 11 2015, 16:32)  Тут имя секции .text не подходит. При линковке есть понятие "входные секции" - это которые компилятор создает в объектных файлах из вашего исходника и "выходные секции" - это в которые линкер складывает входные секции. То есть линкер берет входные секции и размещает их в выходные согласно скрипта. В выходном файле входных секций уже нет, в нем только выходные. Вы правильно разместили свою секцию внутри выходной секции .text. Но имя вашей секции надо было дать какое-то другое. Имя .text компилятор использует для кода. Минус лишний перед именем скрипта:-Wl,-T,version_fw.x А вы строчку KEEP(*(".init3")) из исходника убрали? Попробуйте так: В исходнике Код __attribute__ ((section (".fw_version"))) const char name_fw[] = "xxxx"; В скрипте линкера: Код *(.text) /*тут где-то еще должно быть*/ *(.text.*) KEEP(*(.fw_version)) Вроде получилось. проект собрался. Но выдал 21 предупреждения: c:/program files/atmel/atmel toolchain/avr8 gcc/native/3.4.1061/avr8-gnu-toolchain/bin/../lib/gcc/avr/4.8.1/../../../../avr/lib/avr25/crttn88.o: In function `__vector_1': (.text+0x0)(0,0): warning: internal error: out of range error Все предупреждения касаются векторов прерывания.
|
|
|
|
|
Sep 14 2015, 06:17
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 3-09-11
Из: Минск
Пользователь №: 66 982

|
Цитата(Сергей Борщ @ Sep 11 2015, 17:53)  Это ошибка в линкере. По-хорошему надо писать сообщение об ошибке его авторам. Я на такое не нарывлася. Приложите весь проект в архиве. Я тут поигрался немного с форматом строчки, о точнее с содержимым строки name_fw[]. И заметил такую закономерность. Что если в строке четное количество символов, то проект соберется и выдаст Warning на вектора прерываний. А если в строке не четное количество символов, то все соберется без предупреждений.
|
|
|
|
|
Sep 14 2015, 07:55
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Twin_by @ Sep 14 2015, 09:17)  А если в строке не четное количество символов, то все соберется без предупреждений. Попробуйте тогда сделать так: Код *(.text) /*тут где-то еще должно быть*/ *(.text.*) KEEP(*(.fw_version)) . = ALIGN(2);
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 14 2015, 11:30
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 3-09-11
Из: Минск
Пользователь №: 66 982

|
Цитата(Сергей Борщ @ Sep 14 2015, 10:55)  Попробуйте тогда сделать так: Код *(.text) /*тут где-то еще должно быть*/ *(.text.*) KEEP(*(.fw_version)) . = ALIGN(2); Помогло. Сейчас собирается без предупреждений. И создается два пустых байта после строки содержащей четное количество символов, и один байт если строка содержит не четное количество символов. Но была другая большая проблема. После прошивки микроконтроллера, он отказывался обрабатывать прерывания. Поэтому Код *(.fw_version) KEEP(*(.fw_version)) . = ALIGN(2); перенес из начала секции .text чуть ниже после *(.vectors) KEEP(*(.vectors)). И вроде работает, прерывания и АЦП обрабатывает. Сейчас секция .text приняла следующий вид CODE .text : { *(.vectors) KEEP(*(.vectors)) *(.fw_version) KEEP(*(.fw_version)) . = ALIGN(2); /* For data that needs to reside in the lower 64k of progmem. */ *(.progmem.gcc*) *(.progmem*) . = ALIGN(2); __trampolines_start = .; /* The jump trampolines for the 16-bit limited relocs will reside here. */ *(.trampolines) *(.trampolines*) __trampolines_end = .; /* For future tablejump instruction arrays for 3 byte pc devices. We don't relax jump/call instructions within these sections. */ *(.jumptables) *(.jumptables*) /* For code that needs to reside in the lower 128k progmem. */ *(.lowtext) *(.lowtext*) __ctors_start = .; *(.ctors) __ctors_end = .; __dtors_start = .; *(.dtors) __dtors_end = .; KEEP(SORT(*)(.ctors)) KEEP(SORT(*)(.dtors)) /* From this point on, we don't bother about wether the insns are below or above the 16 bits boundary. */ *(.init0) /* Start here after reset. */ KEEP (*(.init0)) *(.init1) KEEP (*(.init1)) *(.init2) /* Clear __zero_reg__, set up stack pointer. */ KEEP (*(.init2)) *(.init3) KEEP (*(.init3)) *(.init4) /* Initialize data and BSS. */ KEEP (*(.init4)) *(.init5) KEEP (*(.init5)) *(.init6) /* C++ constructors. */ KEEP (*(.init6)) *(.init7) KEEP (*(.init7)) *(.init8) KEEP (*(.init8)) *(.init9) /* Call main(). */ KEEP (*(.init9)) *(.text) . = ALIGN(2); *(.text.*) . = ALIGN(2); *(.fini9) /* _exit() starts here. */ KEEP (*(.fini9)) *(.fini8) KEEP (*(.fini8)) *(.fini7) KEEP (*(.fini7)) *(.fini6) /* C++ destructors. */ KEEP (*(.fini6)) *(.fini5) KEEP (*(.fini5)) *(.fini4) KEEP (*(.fini4)) *(.fini3) KEEP (*(.fini3)) *(.fini2) KEEP (*(.fini2)) *(.fini1) KEEP (*(.fini1)) *(.fini0) /* Infinite loop after program termination. */ KEEP (*(.fini0)) _etext = .; } > text
Сообщение отредактировал IgorKossak - Sep 14 2015, 13:51
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|