реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> avr-gcc, строка символов во FLASH, Как заставить компилятор строки символов размещать во FLASH?
impatt
сообщение Nov 8 2006, 06:14
Сообщение #1


Частый гость
**

Группа: Validating
Сообщений: 169
Регистрация: 10-11-04
Из: Челябинск
Пользователь №: 1 088



Насколько я понимаю, gcc строки символов помещает в ОЗУ.Например:
Код
puts ("test\n");

превращается в примерно следующее:
Код
unsigned char name[] = "test\n";
puts(name);

где name во второй строке есть указатель на область ОЗУ, где находится строка.
Теперь вопрос: как сделать так, чтобы gcc в местах, подобных первому примеру, помещал строки во FLASH и брал указатели соответственно.
Вариант, когда все строки перечисляются в начале программы с атрибутом __attribute__((section(".flash"))), не годятся, ибо неудобно. Точнее, годятся, но неудобно и потому не годятся.

Есть мнения ?
Спасибо.

Сообщение отредактировал impatt - Nov 8 2006, 06:15
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 8 2006, 06:57
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(impatt @ Nov 8 2006, 13:14) *
...Теперь вопрос: как сделать так, чтобы gcc в местах, подобных первому примеру, помещал строки во FLASH и брал указатели соответственно.
Я недавно решал такую проблему с ИАРом. Там есть хедер pgmspace.h, который надо подключить, плюс в командной строке компилера прописать команду --string_literals_in_flash

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


--------------------
Go to the top of the page
 
+Quote Post
jorikdima
сообщение Nov 8 2006, 06:58
Сообщение #3


тут может быть ваша реклама
*****

Группа: Свой
Сообщений: 1 164
Регистрация: 15-03-06
Из: Санкт-Петербург/CA
Пользователь №: 15 280



Это совсем недавно обсуждалось. На самом деле вы подумайте, ведь не могут строки располагаться не в ПЗУ. Иначе как контроллер будет "помнить" строчку test после выключения питания?? ))) Она располагается в ПЗУ (флэш в данном случае), а в момент инициализации контроллера ПРОГРАММНО подобные строки ( глобальные переменные...) перепичываются (копируются) в ОЗУ и далее используются оттуда, чтобы быстрее было.
Go to the top of the page
 
+Quote Post
haker_fox
сообщение Nov 8 2006, 07:17
Сообщение #4


Познающий...
******

Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125



Цитата(jorikdima @ Nov 8 2006, 14:58) *
Это совсем недавно обсуждалось. На самом деле вы подумайте, ведь не могут строки располагаться не в ПЗУ. Иначе как контроллер будет "помнить" строчку test после выключения питания?? ))) Она располагается в ПЗУ (флэш в данном случае), а в момент инициализации контроллера ПРОГРАММНО подобные строки ( глобальные переменные...) перепичываются (копируются) в ОЗУ и далее используются оттуда, чтобы быстрее было.

Наверное дело не в скорости, а в стандарте языка Си... не знаю

impatt ответ на поставленный вопрос Вы найдете в этой теме.


--------------------
Выбор.
Go to the top of the page
 
+Quote Post
impatt
сообщение Nov 8 2006, 07:53
Сообщение #5


Частый гость
**

Группа: Validating
Сообщений: 169
Регистрация: 10-11-04
Из: Челябинск
Пользователь №: 1 088



Цитата(jorikdima @ Nov 8 2006, 09:58) *
На самом деле вы подумайте, ведь не могут строки располагаться не в ПЗУ. Иначе как контроллер будет "помнить" строчку test после выключения питания?? ))) Она располагается в ПЗУ (флэш в данном случае), а в момент инициализации контроллера ПРОГРАММНО подобные строки ( глобальные переменные...) перепичываются (копируются) в ОЗУ и далее используются оттуда.

Это мне известно smile.gif
Go to the top of the page
 
+Quote Post
impatt
сообщение Nov 8 2006, 08:09
Сообщение #6


Частый гость
**

Группа: Validating
Сообщений: 169
Регистрация: 10-11-04
Из: Челябинск
Пользователь №: 1 088



Цитата(haker_fox @ Nov 8 2006, 10:17) *
impatt ответ на поставленный вопрос Вы найдете в этой теме.

Нашел вариации на тему __attribute__((section(".flash"))), оно же макрос PROGMEM или как там его. Мож, я плохо глядел ?...
Интересует именно работоспособность варианта №1 в моём первом посте. Делать заготовки в виде переменных в начале единицы компиляции (файла *.с) неудобно.


Цитата(prottoss @ Nov 8 2006, 09:57) *
Цитата(impatt @ Nov 8 2006, 13:14) *
...Теперь вопрос: как сделать так, чтобы gcc в местах, подобных первому примеру, помещал строки во FLASH и брал указатели соответственно.
Я недавно решал такую проблему с ИАРом. Там есть хедер pgmspace.h, который надо подключить, плюс в командной строке компилера прописать команду --string_literals_in_flash

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

Боюсь, что нет, но позже погляжу: gcc не заточен на микроконтроллеры, он вообще ни на что не заточен. Потому там понятие FLASH вне закона вообще. Что можно сделать, так это, например, не копировать секцию .data в RAM, и как-то заставить линкер подставлять указатель нужным образом. Вообще-то я эту кухню не очень хорошо знаю.
Go to the top of the page
 
+Quote Post
aesok
сообщение Nov 8 2006, 18:22
Сообщение #7


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Цитата(impatt @ Nov 8 2006, 12:09) *
Боюсь, что нет, но позже погляжу: gcc не заточен на микроконтроллеры, он вообще ни на что не заточен. Потому там понятие FLASH вне закона вообще. Что можно сделать, так это, например, не копировать секцию .data в RAM, и как-то заставить линкер подставлять указатель нужным образом. Вообще-то я эту кухню не очень хорошо знаю.


GCC это компилятор стандартного языка C!!!

Первое: В стандартном C есть только ОДИН вид указателя, указатель на ячейку памяти. Нет указателя на флеш, на EEPROM на порты ввода/выводы..... только один указатель который должен ссылаться на все. НО: В стандартном C размер типа 'указателя' равен размеру типа 'int', для AVR-GCC - 16-бит.

И тут для AVR-GCC начинаться проблемы.
У AVR можно насчитать четыре адресных пространства:
1. RAM до 64KB;
2. EEPROM - обычно до несколько килобайт, но есть микросхемы с 144 КВ.
3. Байт адресуемая флеш (когда используется для хранения данных) до 256 КБ на ATmega2560.
4. Память программ до 128Кслов на ATmega2560.

Можно ко всей этой памяти обращаться с помощью одного 16-ти битного указателя? НЕТ НЕЛЬЗЯ!!! А ЕСТЬ ТОЛЬКО ОДИН! И НАДО!!!

Теоретически можно избежать всех проблем если сделать указатель 32-х битным... но представьте себе на сколько возрастет размер кода. А еще и int тоже будет 32-х битным.

Приходиться выкручиваться и применять разные нестандартные средства. В GCC это атрибуты. С помощью атрибутов компилятору указывается в какой памяти разместить переменную.
В RAM, без атрибутов. Во флеш:
char __attribute__((__progmem__)) str[] = "Строка";
или тоже самое:
prog_char str[] PROGMEM = "Строка";

Дальше, в GCC оператор присваивания не работает с переменными которые размещены во флеш (и EEPROM тоже). Например:

prog_char с1 = 'A';
char c2;
c2 = c1;

c2 не будет присвоено значение переменной с1 (А), а будет присвоено значение из адреса &с1, но не из флеш а из адресного пространства RAM. Надо писать:

c2 = pgm_read_byte(&c1);

И наконец ответ на ваш вопрос: разместить строку во флеш и передать в функцию указатель на нее, не объявляя переменную можно так:
puts_P (PSTR("test\n"));


Но внутри функции символы из этой строки вы должны получать используя макрос pgm_read_byte():
puts_P (PGM_P str)
{
char c;
....
c = pgm_read_byte(str);
....

}

Анатолий.

PS: Ответы на другие вопросы: "Что будет если стока не попадет в нижние 64К флеша?", "Почему для ATmega256 хватает 16-ти битноко указателя для 128 Кслов?" - дам если спросити.
Go to the top of the page
 
+Quote Post
PaulS
сообщение Nov 8 2006, 20:24
Сообщение #8





Группа: Новичок
Сообщений: 9
Регистрация: 28-01-05
Пользователь №: 2 265



А что, в GCC модификаторы __flash и __eeprom не работают?
Ужас какой sad.gif

Может так попробовать:
__no_init __eeprom unsigned int count_SMSinput;

или даже лучше так:
typedef unsigned char __flash FDATA;
typedef unsigned char __eeprom EDATA;
чтобы потом вот так:
FDATA AT_prefix[] = "AT";

И с указателями должно быть все ОК. Наверное так надо:
FDATA power_on[] = "POWER ON";
FDATA *ptrF;
а потом что-то типа:
while(*ptrF) *ptrA++ = *ptrF++;

В ИАРе все работает.
Завтра на работу прийду если не забуту, проверю в GCC

Сообщение отредактировал PaulS - Nov 8 2006, 20:28
Go to the top of the page
 
+Quote Post
impatt
сообщение Nov 9 2006, 03:48
Сообщение #9


Частый гость
**

Группа: Validating
Сообщений: 169
Регистрация: 10-11-04
Из: Челябинск
Пользователь №: 1 088



Цитата(aesok @ Nov 8 2006, 21:22) *
GCC это компилятор стандартного языка C!!!
Анатолий.

Анатолий, большое спасибо за комментарий. Правда, всё, что вы написали,я себе внятно представляю.
Насколько я знаю, gcc (вернее, cc1, компилятор С) делает из С текста текст на asm-е, который добивает as, а потом получившийся объектник линукет ld. Вплоть до последнего этапа, в объектных файлах (можно прогнать дизассемблером и убедиться) указатели равны нулю, их потом расставляет линкер. Это, видимо, сделано исходя из того, что именно линкер знает, в каких адресах будут находиться секции кода и данных. Это написано в опциях линкера а также его скриптах. Сам cc1 встретившиеся инициализированные и неинициализированные переменные, а также константы, распихивает по секциям уже на этапе изготовления asm. И на этом же этапе учитываются пожелания в виде атрибутов вида __attribute__((section("имя"))), которые где-то в исходниках avr-libc определены как PROGMEM или я забыл, как дословно.
Вероятно, чтобы добиться результата, то есть, получить ответ на мой первоначальный вопрос, нужно знать, как уломать gcc понимать, что инициализированные локальные строки следует воспринимать как константы и кандидатов на размещение не в секцию .data, а в секцию .text. Предполагаю, что это задача нетривиальная.
Возвращаясь к начальной теме, скажу, что текст наподобии:
Код
const uint8_t text1[] = 'text1\n';//атрибуты принадлежности к FLASH опускаю
const uint8_t text2[] = 'text2\n';//атрибуты принадлежности к FLASH опускаю
//и так далее

//а затем использование:
my_print(text1);//использование указателя с осознанием того, что он указывает не в RAM, но в FLASH
my_print(text2);

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

Цитата(aesok @ Nov 8 2006, 21:22) *
PS: Ответы на другие вопросы: "Что будет если стока не попадет в нижние 64К флеша?", "Почему для ATmega256 хватает 16-ти битноко указателя для 128 Кслов?" - дам если спросити.

Спасибо за предложение smile.gif Я чётко себе представляю, как это делается и что получается smile.gif

Цитата(PaulS @ Nov 8 2006, 23:24) *
А что, в GCC модификаторы __flash и __eeprom не работают?
Ужас какой sad.gif

Применительно к данным работает атрибут, заставляющий помещать данные в любую секцию: __attribute__((section("имя"))), а линкеру потом объяснить, в каких адресах находится секция с этим именем. Вот и всё. Модификаторов, про которые вы упомянули, в gcc нет (как мне известно). Если что-то подобное есть, то это макросы avr-libc, что не есть часть gcc.
Go to the top of the page
 
+Quote Post
haker_fox
сообщение Nov 9 2006, 07:17
Сообщение #10


Познающий...
******

Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125



Цитата(impatt @ Nov 8 2006, 16:09) *
Цитата(haker_fox @ Nov 8 2006, 10:17) *


impatt ответ на поставленный вопрос Вы найдете в этой теме.

Нашел вариации на тему __attribute__((section(".flash"))), оно же макрос PROGMEM или как там его. Мож, я плохо глядел ?...
Интересует именно работоспособность варианта №1 в моём первом посте. Делать заготовки в виде переменных в начале единицы компиляции (файла *.с) неудобно.


Цитата(prottoss @ Nov 8 2006, 09:57) *
Цитата(impatt @ Nov 8 2006, 13:14) *
...Теперь вопрос: как сделать так, чтобы gcc в местах, подобных первому примеру, помещал строки во FLASH и брал указатели соответственно.
Я недавно решал такую проблему с ИАРом. Там есть хедер pgmspace.h, который надо подключить, плюс в командной строке компилера прописать команду --string_literals_in_flash

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

Боюсь, что нет, но позже погляжу: gcc не заточен на микроконтроллеры, он вообще ни на что не заточен. Потому там понятие FLASH вне закона вообще. Что можно сделать, так это, например, не копировать секцию .data в RAM, и как-то заставить линкер подставлять указатель нужным образом. Вообще-то я эту кухню не очень хорошо знаю.


Для одиночной строки

prog_char str_ok[] = "<ok>";


--------------------
Выбор.
Go to the top of the page
 
+Quote Post
aesok
сообщение Nov 9 2006, 16:32
Сообщение #11


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Цитата(impatt @ Nov 9 2006, 07:48) *
Вероятно, чтобы добиться результата, то есть, получить ответ на мой первоначальный вопрос, нужно знать, как уломать gcc понимать, что инициализированные локальные строки следует воспринимать как константы и кандидатов на размещение не в секцию .data, а в секцию .text.


Я писал про это в конце своего предыдущего поста.

Анатолий.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 9 2006, 16:44
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(aesok @ Nov 9 2006, 23:32) *
Цитата(impatt @ Nov 9 2006, 07:48) *

Вероятно, чтобы добиться результата, то есть, получить ответ на мой первоначальный вопрос, нужно знать, как уломать gcc понимать, что инициализированные локальные строки следует воспринимать как константы и кандидатов на размещение не в секцию .data, а в секцию .text.


Я писал про это в конце своего предыдущего поста.


Анатолий.


Почитал я все ваши размышления по поводу gcc...Мдя... А чем, не нравится ИАР? Или Вы программируете в пингвинных осях? Зачем столько сложностей?


--------------------
Go to the top of the page
 
+Quote Post
aesok
сообщение Nov 9 2006, 17:26
Сообщение #13


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Цитата(prottoss @ Nov 9 2006, 20:44) *
Почитал я все ваши размышления по поводу gcc...Мдя... А чем, не нравится ИАР? Или Вы программируете в пингвинных осях? Зачем столько сложностей?


Религиозные убеждения.

Анатолий.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 9 2006, 17:37
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(aesok @ Nov 10 2006, 00:26) *
Религиозные убеждения.
Ясна


--------------------
Go to the top of the page
 
+Quote Post
impatt
сообщение Nov 10 2006, 03:04
Сообщение #15


Частый гость
**

Группа: Validating
Сообщений: 169
Регистрация: 10-11-04
Из: Челябинск
Пользователь №: 1 088



Цитата(aesok @ Nov 9 2006, 19:32) *
Я писал про это в конце своего предыдущего поста.

Да, понятно. Как вариант годится, спасибо.


Цитата(prottoss @ Nov 9 2006, 19:44) *
Почитал я все ваши размышления по поводу gcc...Мдя... А чем, не нравится ИАР? Или Вы программируете в пингвинных осях? Зачем столько сложностей?

Может, это и ко мне вопрос адресован ?
Если так, то могу сказать, что этот компилятор интересен своей настраиваемостью, многоплатформенностью (включая ОС, на которой запускается и архитектуры). Мне, например, интересны Линукс на x86 и ARM9, и ещё по работе приходится дело иметь с AVR-ками. Мне видится более удобным использовать один компилятор для всего.
Ну и понимая кое-какие аспекты работы этого компилятора появляется интерес полазить в его исходных кодах или даже поучаствовать в его развитии (до этого пока далеко).
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 18:00
Рейтинг@Mail.ru


Страница сгенерированна за 0.01533 секунд с 7
ELECTRONIX ©2004-2016