Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: организовать сегмент во flash
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
1921
Прочитал, как хранить данные во fash по определённому адресу с помощью директивы __location.
Проблема возникла в том, что по этому адресу размещается только константа, следующая непосредственно за директивой. Остальные же линковщик распихивает по своему разумению. Можно ли и как организовать сегмент в flash по определённому адресу, чтобы в нём лежала группа переменных?
Читал-читал - ничего не понял...
#pragma location=0x8000
const unsigned char buf[5]={0,0,0,0,0}; - вот эта лежит на 8000
const unsigned char buf1[10]={48,49,50,51,52,53,54,55,56,57}; - а все ниже где-то в другом месте.
const unsigned char buf2[8]={0,1,2,3,4,5,6,7};
rezident
Дело в том, что эта прагма действиует только на одно последующее объявление переменной или константы. Чтобы не заморачиваться с кучей строк прагмы и ручным вычислением адресов, объедините свои константы в структуру.
1921
Цитата(rezident @ Jan 19 2011, 19:23) *
Дело в том, что эта прагма действиует только на одно последующее объявление переменной или константы. Чтобы не заморачиваться с кучей строк прагмы и ручным вычислением адресов, объедините свои константы в структуру.


А прагма будет действовать на всю структуру?
Хотя не очень охота возиться с длинными записями типа "структура.элемент". Удобнее было бы организовать сегмент, указать адрес его размещения и размер (например, 512 байт, чтобы если тереть, так уж всё!), а при объявлении констант указывать, в каком сегменте их разместить. Как-то так. Может, черканёте строчки три, как это сделать? Я чего-то не нашёл примеров. В этом сегменте я буду держать переменные (параметры), которые могут иногда изменяться (настройки там всякие...).
Кстати ещё вопросик. Тут один товарисч из scanti сказал, что время непрерывной записи сегмента ограничено. Долгое стояние в этом режиме приводит к развалу начала записываемого сектора, т.к. нельзя долго держать включенным генератор напряжения записи. Я так понимаю, это определяет минимальную частоту MCLK при этой процедуре. Не подскажите, какую величину имеет это время? Он навскидку не смог сказать.
MrYuran
По-моему, есть ещё #pragma section или что-то навроде.
Объявите свою секцию и пихайте туда.
Хотя структура в любом случае красивее, данные связаны и сгруппированы.
Вот ещё из FAQ от Сергея Борща:
Цитата
14)
Q: Как при написании программы разместить начальные данные в сегменте информационной памяти Flash?
A:
Для компилятора IAR в управляющем файле линкера MSP430xxxxxx.xcl определен сегмент INFO. Поместить в него данные можно при помощи команды компилятору #pragma memory = constseg(INFO) и атрибута const. Например:
#pragma memory = constseg(INFO)
const char * HelloString="Hello";
const float One = 1.0;
#pragma memory = default;
Эти данные попадут в сегмент INFO при программировании кристалла.
Сергей Борщ
QUOTE (MrYuran @ Jan 20 2011, 13:41) *
Вот ещё из FAQ от Сергея Борща:
Когда это писалось, компилятор имел версию 2.хх
MrYuran
Цитата(Сергей Борщ @ Jan 20 2011, 14:51) *
Когда это писалось, компилятор имел версию 2.хх

Значит, надо взять в руки Compiler Reference и найти 10 отличий sm.gif
1921
Видите ли, боюсь, но память info меня не устроит. "Маловато будет!" Я бы откусил пару блоков по 512 сверху где-нибудь. И дал бы понять линковщику, что туда ничего писать не надо. В пиках я просто забивал пустой буфер до границы сектора. Здесь интереснее: не используемые буфера вообще игнорируются. Не, я могу чисто символически его где-нибудь в программе дёрнуть, но это по-моему неправильно. Как бы указать линкеру явно, чтобы не лез, куда его не просят? Хедеры и прочее переписывать не хочу, хочу, чтобы из программы. У структуры длинные имена, лень каждый раз писать. Хочу чтобы без структур. В общем, буду пинать его ногами, пока не устану или он не сдастся!!!
rezident
Цитата(1921 @ Jan 20 2011, 16:20) *
А прагма будет действовать на всю структуру?
Конечно. Ведь структура это единый объект с точки зрения компиляции.
Цитата(1921 @ Jan 20 2011, 16:20) *
Хотя не очень охота возиться с длинными записями типа "структура.элемент". Удобнее было бы организовать сегмент, указать адрес его размещения и размер (например, 512 байт, чтобы если тереть, так уж всё!), а при объявлении констант указывать, в каком сегменте их разместить. Как-то так. Может, черканёте строчки три, как это сделать? Я чего-то не нашёл примеров. В этом сегменте я буду держать переменные (параметры), которые могут иногда изменяться (настройки там всякие...).
Читайте описание #pragma в разделе data alignment в User manual на компилятор, а о создании своих секций в User manual на линкер. Ей-богу будет больше пользы, чем от примера из двух строчек. sm.gif
Цитата(1921 @ Jan 20 2011, 16:20) *
Я так понимаю, это определяет минимальную частоту MCLK при этой процедуре. Не подскажите, какую величину имеет это время?
Допустимый диапазон частот для FTG указан в datasheet конкретного кристалла, навскидку что-то около 300-400кГц. А с медленным MCLK как какая-то другая беда была. Типа когда MCLK от VLO тактируют. Подробностей уже не помню. Где-то здесь был топик на эту тему.
jorikdima
Цитата(1921 @ Jan 20 2011, 14:20) *
Кстати ещё вопросик. Тут один товарисч из scanti сказал, что время непрерывной записи сегмента ограничено. Долгое стояние в этом режиме приводит к развалу начала записываемого сектора, т.к. нельзя долго держать включенным генератор напряжения записи. Я так понимаю, это определяет минимальную частоту MCLK при этой процедуре. Не подскажите, какую величину имеет это время? Он навскидку не смог сказать.

Читайте даташит на кристал (не юзер гид), раздел Flash. Время порядка десятка мс. К MCLK это имеет очень далекое отношение, ибо процесс записи это несколько команд. Ну не делайте MCLK менее килогерца просто sm.gif
1921
Цитата(rezident @ Jan 19 2011, 19:23) *
Дело в том, что эта прагма действиует только на одно последующее объявление переменной или константы. Чтобы не заморачиваться с кучей строк прагмы и ручным вычислением адресов, объедините свои константы в структуру.

А вот не хочет такая запись компилиться!

#pragma location=0x8000
struct
{
const unsigned char buf[5];
const unsigned char buf1[10];
const unsigned char buf2[8];
} MyPar ={0,0,0,0,0,48,49,50,51,52,53,54,55,56,57,0,1,2,3,4,5,6,7};
Говорит, что такая прагма тут не применима.
jorikdima
А так:

Код
typedef struct
{
unsigned char buf[5];
unsigned char buf1[10];
unsigned char buf2[8];
} MyPar;

#pragma location=0x8000
const MyPar par ={0,0,0,0,0,48,49,50,51,52,53,54,55,56,57,0,1,2,3,4,5,6,7};

?
1921
Цитата(jorikdima @ Jan 20 2011, 17:20) *
А так:

Код
typedef struct
{
unsigned char buf[5];
unsigned char buf1[10];
unsigned char buf2[8];
} MyPar;

#pragma location=0x8000
const MyPar par ={0,0,0,0,0,48,49,50,51,52,53,54,55,56,57,0,1,2,3,4,5,6,7};

?


Неа. Нехотит.
rezident
Вот так попробуйте
Код
typedef struct MyPar_t
{
  unsigned char buf[5];
  unsigned char buf1[10];
  unsigned char buf2[8];
} MyPar_t;

#pragma location=0x8000
const MyPar_t MyParInit = {0,0,0,0,0,48,49,50,51,52,53,54,55,56,57,0,1,2,3,4,5,6,7};
#pragma required=MyParInit

#pragma location=0x8000
__no_init const MyPar_t MyPar;
#pragma required=MyPar

будет warning с предупреждением о том, что вы две структуры в одно адресное пространство поместили. Но на него можно не обращать внимания. В самой программе следует работать со структурой MyPar. Именно с ней потому, что IAR оптимизирует обращение к константам, подставляя их значение по месту использования. В результате MyParInit он конечно разместит там, где вы его попросите, но извлекать значения из нее не будет, воспользовавшись теми их значениями, которыми вы проинициализировали структуру на момент компиляции программы.
1921
будет warning с предупреждением о том, что вы две структуры в одно адресное пространство поместили. Но на него можно не обращать внимания.
Да нет, там не вонинг, а еррор. На него нельзя не обратить.

Может, ну его... переписать пару строк в линкере, организовав два сегмента под свои нужды, раз уж он так не хочет?
rezident
А блин! там const лишний. Извиняюсь. Вот так вторую нужно.

Код
#pragma location=0x8000
__no_init MyPar_t MyPar;
#pragma required=MyPar
1921
Цитата(rezident @ Jan 20 2011, 17:42) *
А блин! там const лишний. Извиняюсь. Вот так вторую нужно.

Код
#pragma location=0x8000
__no_init MyPar_t MyPar;
#pragma required=MyPar


То же самое. Ругается, что два сегмента перекрываются.
rezident
Цитата(1921 @ Jan 20 2011, 19:53) *
То же самое. Ругается, что два сегмента перекрываются.
Я про это предупреждал. Ну и пусть ругается, лишь бы компиляция шла sm.gif У вас случайно в опциях не стоит "принимать все warning как error", прекращая компиляцию?
1921
Цитата(rezident @ Jan 20 2011, 17:57) *
Я про это предупреждал. Ну и пусть ругается, лишь бы компиляция шла sm.gif У вас случайно в опциях не стоит "принимать все warning как error", прекращая компиляцию?

Проверил. Не стоит.
rezident
Цитата(1921 @ Jan 20 2011, 20:02) *
Проверил. Не стоит.
Установите "птичку" в Options -> Linker -> Diagnostics -> Segment overlap warning.
1921
Цитата(rezident @ Jan 20 2011, 18:19) *
Установите "птичку" в Options -> Linker -> Diagnostics -> Segment overlap warning.


И О ЧУДО!!!
ОНО ЗАРАБОТАЛО!!!
СЛАВА РЕЗИДЕНТУ!!!

typedef struct MyPar_t
{
unsigned char buf[5];
unsigned char buf1[10];
unsigned char buf2[8];
} MyPar_t;

#pragma location=0x8000
const MyPar_t MyParInit = {0,0,0,0,0,48,49,50,51,52,53,54,55,56,57,0,1,2,3,4,5,6,7};
#pragma required=MyParInit

#pragma location=0x8000
__no_init MyPar_t MyPar;
#pragma required=MyPar

Это уже наглость, конечно. Но, может, хотя бы в двух словах поясните, зачем нужно было объявление двух структур? Или отошлите к первоисточникам. А то как-то непонятно...
rezident
Перечитайте еще раз сообщение №13. Я там пояснил для чего нужно объявление двух структур. Если вы настройки менять не собираетесь (внутрипрограммно перепрограммируя данные этого сегмента флешь), то можно и одной обойтись или вообще дефайнами. Результат будет одинаковый.
=DS=
В последних версиях компилятора введен специальный атрибут __persistent именно для подобных целей. Переменные с этим атрибутом не инициализиуются на старте и группируются в сегменте DATA_P/DATA20_P, который при линковке можно расположить где угодно.
1921
Цитата(=DS= @ Jan 21 2011, 22:17) *
В последних версиях компилятора введен специальный атрибут __persistent именно для подобных целей. Переменные с этим атрибутом не инициализиуются на старте и группируются в сегменте DATA_P/DATA20_P, который при линковке можно расположить где угодно.

У меня persistent не работает, не дорос ишшо до нужной версии. Попробовал все подсказанные варианты, всё-таки решил подправить линкер. Ничего, не обеднеет, из 256к 512 байт под доп сегмент. Просто, дёшево и сердито.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.