Перейти к содержанию
    

про --gc-sections где-то читал что могут быть проблеммы с отладкой. вечером поищю где про это написано.
В некоторых версиях он выдавал warning "могут быть проблемы с отладкой на некоторых targets". Пока на такие проблемы не натыкался (внутрисхемной отладкой не пользуюсь), а уточнений - на каких именно targets и какие именно проблемы могут быть - не попадалось.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Здравствуйте уважаемые форумчане!

 

У меня проблемка нарисовалась с поддержкой ядер 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! :help:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Help! :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/.

 

Анатолий.

Изменено пользователем aesok

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

К Анатолию

 

Спасибо за информацию о скором выходе нового WinAVR - буду ждать.

 

А пока выкручусь через "левое ухо" - выкинуть функции использующие пролог/эпилог я пока не готов - ведь им надо или писать или искать замену (слишком много дел), я скомпилировал проект в версии 20070122 с библиотеками libc версии 1.6.1 и ключом -Os. Получилось 128866 байт (в версии 20080610 - 143844). Таким образом проблема решилась - но проект постоянно растет и если патчи не будут учтены в новой версии WinAVR - беда!

 

А может есть способ заставить линкер собирать сначала библиотечные функциии (из libc.a libm.a libgcc.a) а потом остальные модули?

Изменено пользователем Chak

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тестовый пример пожалуйста приведите.

 

Анатолий.

 

Есть строка вида (к примеру)

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 (и более ранних) проект полностью рабочий!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Есть строка вида (к примеру)

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.

 

Анатлий.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Простите, но я там не нашел ответа на свой вопрос, на что именно вы хотели мне указать???

 

Может я неправильно задал вопрос....Есть кусок кода

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 (как это делала более ранняя версия)???

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

строку MenuItem1 GCC 4.2.2 ложит во flash, а GCC 4.3.0 ложит в ram!!! Как сделать, чтоб GCC 4.3.0 входящий в состав WinAVR-20080610, клал строку во flash (как это делала более ранняя версия)???

 

Или Вы запутались или одно из двух. В приведенном коде у Вас фигурировало константное выражение. Ессно мона его расположить где удобнее оптимайзеру :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Но если пойти по приведенной aesok ссылке, то там некий товарищь, именно таким вот методом

const char MenuItem1[] PROGMEM = "Menu Item 1";

размещает константы не там где хочет оптимизатор, а там где нада!

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Но если пойти по приведенной 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

, а не на определения строк.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Заменил все prog_char на char имя_строки[] PROGMEM и без изменения кода функций вывода, все вдруг чудесно заработало...

Собсно, а что случилось с prog_char в новых версиях???

почему выражения

const   prog_char   Punkt1[]   =   {"Строка"};

и

const   char   Punkt1[]   PROGMEM   =   {"Строка"};

не равносильны???

Вроде это одно и тоже....

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

почему выражения

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.

 

Анатолий.

Изменено пользователем aesok

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Анатолий, спасибо за ответы, очень помогло!!!=)

 

Я пытаюсь разобраться, но все-равно есть некоторые вопросы...

 

есть массив строк

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 - компилятор такого предупреждения не выдает...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Во втором указатель Punkt1 с атрибутом "progmem" ссылается на const char, то есть Punkt1 расположен в памяти программ, а константная строка в RAM.

Анатолий.

Как я понял, этот вариант работает в WinAVR2008....

Но ведь таким образом расходуется драгоценная RAM.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поставил сабж. Размер обоих проектов увеличился ровно на 32 байта каждый. Работоспособность не изменилась. Глупые строки вида

lds r24, 0x013A

lds r25, 0x013B

mov r18, r24

mov r19, r25

- остались. В чем отличие и кому нужны 32 байта - так и не понял.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...