Сергей Борщ 119 30 июня, 2008 Опубликовано 30 июня, 2008 · Жалоба про --gc-sections где-то читал что могут быть проблеммы с отладкой. вечером поищю где про это написано.В некоторых версиях он выдавал warning "могут быть проблемы с отладкой на некоторых targets". Пока на такие проблемы не натыкался (внутрисхемной отладкой не пользуюсь), а уточнений - на каких именно targets и какие именно проблемы могут быть - не попадалось. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Chak 0 30 июня, 2008 Опубликовано 30 июня, 2008 · Жалоба Здравствуйте уважаемые форумчане! У меня проблемка нарисовалась с поддержкой ядер AVR с размером памяти 256к. При обращении к библиотечным функциям с переменным числом параметров (например fprint) компилятор встраивает вызовы к встроенным макросам пролог/эпилог (__prologue_saves__ / __epilogue_restores__ - если быть точным) из библиотеки libgcc.a. Беда в том, что данные для этих макросов, которые готовятся на этапе вызова функций, совершенно не учитывают размера памяти больше чем 128к (64к слов), то есть, инициализируются регистры Z (ZH,ZL), а в макросах используеться инструкция EIJMP, для полноценной работы которой надо еще установить регистр EIND. Вот и получается, что если библиотечные функции с переменным числов параметров располагаються в адресах выше чем 128к, то вся програма перестает работать. Решение проблемы - или исправлять libgcc.a (что для меня слишком сложно - я программирующий апаратчик) или заставить линкер располагать эти функции в нижних адресах (а как это сделать я не смог разобраться)... Может кто подскажет другой вариант? Я перепробовал все версии WinAVR начиная с 20070122, привожу фрагменты листинга (при компиляции нету ни ошибок ни предупреждений): Вот одна из библиотечных функций: 00020896 <fprintf_P>: 20896: a0 e0 ldi r26, 0x00 ; 0 20898: b0 e0 ldi r27, 0x00 ; 0 // здесь загружается адрес возврата // из __prologue_saves__ - это должен быть // адрес инструкции "ldd r16, Y+8" - 0х0208а2 // а у нас только 0х0451 х 2 = 0х08а2, // а старшая часть адреса 0х02 нигде не фиксируется!! 2089a: e1 e5 ldi r30, 0x51 ; 81 2089c: f4 e0 ldi r31, 0x04 ; 4 2089e: 0d 94 d9 0c jmp 0x219b2 ; 0x219b2 <__prologue_saves__+0x1c> 208a2: 08 85 ldd r16, Y+8 ; 0x08 208a4: 19 85 ldd r17, Y+9 ; 0x09 а вот злополучная __prologue_saves__ : 00021996 <__prologue_saves__>: 21996: 2f 92 push r2 ... 219b4: 1f 93 push r17 219b6: cf 93 push r28 219b8: df 93 push r29 219ba: cd b7 in r28, 0x3d ; 61 219bc: de b7 in r29, 0x3e ; 62 219be: ca 1b sub r28, r26 219c0: db 0b sbc r29, r27 219c2: 0f b6 in r0, 0x3f ; 63 219c4: f8 94 cli 219c6: de bf out 0x3e, r29 ; 62 219c8: 0f be out 0x3f, r0 ; 63 219ca: cd bf out 0x3d, r28 ; 61 219cc: 19 94 eijmp // естественно после этой инструкции мы "улетаем" // по адресу 0х0008а2 (проверено в отладчике)! Help! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aesok 0 30 июня, 2008 Опубликовано 30 июня, 2008 (изменено) · Жалоба Help! Хм... посылали Эрику патч для решения этой проблемы но почему-то он его не добавил... Ждите следующую версию WinAVR. А пока исключите из проекта функции которые используют __prologue_saves__ / __epilogue_restores__ и выкинете ключик -mcall-prologues если вы его использовали. Можете еще поискать кого нибудь кто сможет вам собрать avr-libc внеся изменения в файл avr-libc/devtools/gen-avr-lib-tree.sh: -СFLAGS_SPACE="-mcall-prologues -Os" +CFLAGS_SPACE="-Os" Правда устанавливать avr-libc нужно будет ручками... хотя будет достаточно заменить *.a файлы в директори /avr/lib/avr6/. Анатолий. Изменено 30 июня, 2008 пользователем aesok Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Chak 0 1 июля, 2008 Опубликовано 1 июля, 2008 (изменено) · Жалоба К Анатолию Спасибо за информацию о скором выходе нового WinAVR - буду ждать. А пока выкручусь через "левое ухо" - выкинуть функции использующие пролог/эпилог я пока не готов - ведь им надо или писать или искать замену (слишком много дел), я скомпилировал проект в версии 20070122 с библиотеками libc версии 1.6.1 и ключом -Os. Получилось 128866 байт (в версии 20080610 - 143844). Таким образом проблема решилась - но проект постоянно растет и если патчи не будут учтены в новой версии WinAVR - беда! А может есть способ заставить линкер собирать сначала библиотечные функциии (из libc.a libm.a libgcc.a) а потом остальные модули? Изменено 1 июля, 2008 пользователем Chak Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kurtis 0 1 июля, 2008 Опубликовано 1 июля, 2008 · Жалоба Тестовый пример пожалуйста приведите. Анатолий. Есть строка вида (к примеру) const prog_char glob_menu_str[3][14]= { "Строка 1", "Строка 2", "Строка 3", }; После компилирования получаю Project.elf далее делаю avr.nm -n Project.elf > file.txt и поиском ищу glob_menu_str.... в версии gcc 4.2.2 и более ранних получаю 00000326 t glob_menu_str т.е. если судить по символу t то оно легло в секцию с кодом но когда я использую gcc 4.3.0 то получаю такую вот картину 00800591 d _ZL13glob_menu_str оно легло во внешнее озу Далее в коде используется strlen_P, strncpy_P, pgm_read_byte и тд, т.е. думается что мы работаем с переменными расположенными в секции кода... З.Ы. При использовании GCC 4.2.2 (и более ранних) проект полностью рабочий!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aesok 0 1 июля, 2008 Опубликовано 1 июля, 2008 · Жалоба Есть строка вида (к примеру) const prog_char glob_menu_str[3][14]= { "Строка 1", "Строка 2", "Строка 3", }; Прочтите [TUT] [C] GCC and the PROGMEM Attribute , PART II - More advanced uses of PROGMEM. Анатлий. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kurtis 0 1 июля, 2008 Опубликовано 1 июля, 2008 · Жалоба Простите, но я там не нашел ответа на свой вопрос, на что именно вы хотели мне указать??? Может я неправильно задал вопрос....Есть кусок кода const char MenuItem1[] PROGMEM = "Menu Item 1"; int main() { unsigned int a; a = pgm_read_word(&MenuItem1[4]); mTest1 = a; ............. return 0; } строку MenuItem1 GCC 4.2.2 ложит во flash, а GCC 4.3.0 ложит в ram!!! Как сделать, чтоб GCC 4.3.0 входящий в состав WinAVR-20080610, клал строку во flash (как это делала более ранняя версия)??? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 1 июля, 2008 Опубликовано 1 июля, 2008 · Жалоба строку MenuItem1 GCC 4.2.2 ложит во flash, а GCC 4.3.0 ложит в ram!!! Как сделать, чтоб GCC 4.3.0 входящий в состав WinAVR-20080610, клал строку во flash (как это делала более ранняя версия)??? Или Вы запутались или одно из двух. В приведенном коде у Вас фигурировало константное выражение. Ессно мона его расположить где удобнее оптимайзеру :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kurtis 0 1 июля, 2008 Опубликовано 1 июля, 2008 · Жалоба Но если пойти по приведенной aesok ссылке, то там некий товарищь, именно таким вот методом const char MenuItem1[] PROGMEM = "Menu Item 1"; размещает константы не там где хочет оптимизатор, а там где нада! У меня вызывает искреннее удивление, когда в новой версии компилятора, вдруг перестает работать код, который до этого работал много-много лет....Возможно я зациклился на том что код работал, и значит он корректен, и не вижу какой-то явной ошибки.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mdmitry 0 1 июля, 2008 Опубликовано 1 июля, 2008 · Жалоба Но если пойти по приведенной aesok ссылке, то там некий товарищь, именно таким вот методом const char MenuItem1[] PROGMEM = "Menu Item 1"; размещает константы не там где хочет оптимизатор, а там где нада! У меня вызывает искреннее удивление, когда в новой версии компилятора, вдруг перестает работать код, который до этого работал много-много лет....Возможно я зациклился на том что код работал, и значит он корректен, и не вижу какой-то явной ошибки.... Полный код примера из описания avr-libc: #include <avr/pgmspace.h> const char foo[] PROGMEM = "Foo"; const char bar[] PROGMEM = "Bar"; PGM_P array[2] PROGMEM = { foo, bar }; int main (void) { char buf[32]; PGM_P p; int i; memcpy_P(&p, &array[i], sizeof(PGM_P)); strcpy_P(buf, p); return 0; } Это для WinAVR-20071221. Для новых версий не смотрел. aesok скорее всего указывал на массив строк PGM_P array , а не на определения строк. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kurtis 0 1 июля, 2008 Опубликовано 1 июля, 2008 · Жалоба Заменил все prog_char на char имя_строки[] PROGMEM и без изменения кода функций вывода, все вдруг чудесно заработало... Собсно, а что случилось с prog_char в новых версиях??? почему выражения const prog_char Punkt1[] = {"Строка"}; и const char Punkt1[] PROGMEM = {"Строка"}; не равносильны??? Вроде это одно и тоже.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aesok 0 1 июля, 2008 Опубликовано 1 июля, 2008 (изменено) · Жалоба почему выражения const prog_char Punkt1[] = {"Строка"}; и const char Punkt1[] PROGMEM = {"Строка"}; не равносильны??? Вроде это одно и тоже.... В первом случае указатель Punkt1 ссылается на const char с атрибутом "progmem", то есть на константную строку расположенную в памяти программ. Во втором указатель Punkt1 с атрибутом "progmem" ссылается на const char, то есть Punkt1 расположен в памяти программ, а константная строка в RAM. Для общего развития: const Pointers The keyword const for pointers can appear before the type, after the type, or in both places. The following are legal declarations: const int * ptr1; /* A pointer to a constant integer: the value pointed to cannot be changed */ int * const ptr2; /* A constant pointer to integer: the integer can be changed, but ptr2 cannot point to anything else */ const int * const ptr3; /* A constant pointer to a constant integer: neither the value pointed to nor the pointer itself can be changed */ Declaring an object to be const means that the this pointer is a pointer to a const object. A const this pointer can by used only with const member functions. Анатолий. Изменено 1 июля, 2008 пользователем aesok Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kurtis 0 3 июля, 2008 Опубликовано 3 июля, 2008 · Жалоба Анатолий, спасибо за ответы, очень помогло!!!=) Я пытаюсь разобраться, но все-равно есть некоторые вопросы... есть массив строк const char glob_menu_str[8][14] PROGMEM = { "1.Строка1", "1.Строка1", ...... }; далее где-то в коде вызывается функция вывода на ЖКИ (на самом деле это функция копирования значения из памяти в массив данных, который затем уже будет куда-то выводится, не обязательно на ЖКИ) LCD_abc1(glob_menu_str[glob_counter],1); ну и собственно сам код этой функции void LCD_abc1(const char * [b]_str[/b], uint8_t _pos) { uint8_t i = _pos; //size_t _strlen; uint8_t _strlen; uint8_t lcd_temp[32]; _strlen=strlen_P([b]_str[/b]); if(_strlen>(32-_pos)) _strlen=32-_pos; strncpy_P((char*)(&lcd_temp),[b]_str[/b],_strlen+1); while(i<32) { if(lcd_temp[i-_pos]==0x00) break; LCD_str[i] = pgm_read_byte(&LCD_simb[lcd_temp[i-_pos]]); ++i; } //LCD_str[i] - Временные массив, где хранится текущий "экран" //LCD_simb - Таблица символов для ЖКИ } Вроде все красиво, все в железе работает, но компилятор ругается warning: only initialized variables can be placed into program memory areaна все строки описанные подобным образом const char glob_menu_str[8][14] PROGMEM = Непонятно почему возникает такое предупреждение, скомпилировал код в более ранних версиях WinAVR - компилятор такого предупреждения не выдает... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 60 4 июля, 2008 Опубликовано 4 июля, 2008 · Жалоба Во втором указатель Punkt1 с атрибутом "progmem" ссылается на const char, то есть Punkt1 расположен в памяти программ, а константная строка в RAM. Анатолий. Как я понял, этот вариант работает в WinAVR2008.... Но ведь таким образом расходуется драгоценная RAM. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
777777 0 18 июля, 2008 Опубликовано 18 июля, 2008 · Жалоба Поставил сабж. Размер обоих проектов увеличился ровно на 32 байта каждый. Работоспособность не изменилась. Глупые строки вида lds r24, 0x013A lds r25, 0x013B mov r18, r24 mov r19, r25 - остались. В чем отличие и кому нужны 32 байта - так и не понял. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться