Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: IAR icf
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
Alechek
Сделал эмуляцию EEPROM, хочу разместить в конце FLASH памяти. Соответственно, расположение должно передаваться в код с линковщика.

Определил в icf
Цитата
define exported symbol __NVRAM_page_size__ = 1024;
define exported symbol __ICFEDIT_region_NVRAM_pages__ = 2;

define block NVR with alignment = __NVRAM_page_size__,
size = __NVRAM_page_size__ * __ICFEDIT_region_NVRAM_pages__ { };

"NVRAM" : place at end of ROM_region { block NVR };


Все работает хорошо, за исключением одного: линковщик не знает, что это read-only регион памяти. В статистике своей относит его к readwrite data.
Код
"NVRAM":                                    0x800
  NVR                          0x08003800   0x800  <Block>
    NVR               uninit   0x08003800   0x800  <Block tail>
                             - 0x08004000   0x800
.......
    Module                 ro code  ro data  rw data
    ------                 -------  -------  -------
...................
    Gaps                                  2
    Linker created                       43    2 560


Как бы на программу не влияет, но для оценки ресурсов нужно производить лишние математические действия...
Есть варианты сказать линкеру, что этот блок - "readonly data"?
Dog Pawlowa
Цитата(Alechek @ May 15 2016, 11:46) *
Сделал эмуляцию EEPROM, хочу разместить в конце FLASH памяти.

Дежавю... Совсем недавно эта тема долго болталась, по моему на Сахаре.
По моему, автор пришел к выводу что проще всего вручную задавать.
desh
Объявите все переменные из этого блока как const. Должно помочь.
А я делаю так: в icf уменьшаю размер памяти на требуемый размер EEPROM и пишу в эту память как во внешнюю EEPROM.
amiller
А если так в icf файле (IAR):
CODE

define symbol __region_EEPROM_start__ = 0x08006000; /* 4кбайт = 2 сектора */
define symbol __region_EEPROM_end__ = 0x08006FFF;

define region EEPROM_region = mem:[from __region_EEPROM_start__ to __region_EEPROM_end__];

place in EEPROM_region { readonly section my_eeprom };
jcxz
Цитата(Alechek @ May 15 2016, 14:46) *
Есть варианты сказать линкеру, что этот блок - "readonly data"?

В исходниках:
u8 const eeprom[EEPROM_SIZE] @ ".eeprom";
В icf-файле скомпоновать секцию ".eeprom" в нужный регион памяти.
Alechek
Цитата(jcxz @ May 15 2016, 23:25) *
В исходниках:
u8 const eeprom[EEPROM_SIZE] @ ".eeprom";
В icf-файле скомпоновать секцию ".eeprom" в нужный регион памяти.


Неудобно, что EEPROM_SIZE из icf файла взять не получится. Надо будет конфигурировать память в 2-х местах.

Но так в любом случае вылезает как минимум 2 проблемы:
1. eeprom будет линковаться в файл. а это
а) размер бинарной прошики полностью равен размеру флеша (при расположении eeprom в конце памяти)
б) при перепрошивке eeprom затирается
2. и даже затирается eeprom не в 0xFF, а, согласно стандарту C, в 0x00!

Головняк покруче, чем нарушение статистики, как в первом посте.

SSerge
Цитата(Alechek @ May 16 2016, 12:21) *
Неудобно, что EEPROM_SIZE из icf файла взять не получится. Надо будет конфигурировать память в 2-х местах.

Если прочитать в EWARM_DevelopmentGuide.ENU.pdf раздел "Using symbols, expressions, and numbers":
define [ exported ] symbol name = expr;
и
export symbol name;
то получится.

Символ, объявленный в .icf как экспортируемый в тексте программы объявляется как extern и его можно таким образом использовать.
jcxz
Цитата(Alechek @ May 16 2016, 11:21) *
Неудобно, что EEPROM_SIZE из icf файла взять не получится. Надо будет конфигурировать память в 2-х местах.

Уже ответили - читайте мануал.

Цитата(Alechek @ May 16 2016, 11:21) *
Но так в любом случае вылезает как минимум 2 проблемы:
1. eeprom будет линковаться в файл. а это
а) размер бинарной прошики полностью равен размеру флеша (при расположении eeprom в конце памяти)

Ложь. Мой проект .icf:
define region FLASH_regionA = mem:[from 0x00000000 to 0x000002FB];
define region FLASH_regionCRP = mem:[from 0x000002FC to 0x000002FF];
define region FLASH_regionB = mem:[from 0x00001000 to 0x00077FFF];
define region FLASH_regionC = mem:[from 0x00078000 to 0x0007FFFF];
...
place in FLASH_regionA {block IMAGE_HEAD};
place in FLASH_regionC {section .iapMem};
place in FLASH_regionB {ro};

".iapMem" у меня это как раз область эмуляции EEPROM во FLASH программ.
Размер .bin == 49152 байта.
Размер бинарника вообще не от этого зависит.

Цитата(Alechek @ May 16 2016, 11:21) *
б) при перепрошивке eeprom затирается

Кем? Так не затирайте.

Цитата(Alechek @ May 16 2016, 11:21) *
2. и даже затирается eeprom не в 0xFF, а, согласно стандарту C, в 0x00!

Не знаю кем она у Вас там затирается, но у меня в разных проектах почему-то не затирается.
Alechek
Цитата(SSerge @ May 16 2016, 12:39) *
Если прочитать в EWARM_DevelopmentGuide.ENU.pdf раздел "Using symbols, expressions, and numbers":
define [ exported ] symbol name = expr;
и
export symbol name;
то получится.

Вышлю ящик пива тому, кто скомпилит
Код
extern char A;
const char EEPROM[A];


Цитата(jcxz @ May 16 2016, 13:57) *
Ложь. Мой проект .icf:
place in FLASH_regionA {block IMAGE_HEAD};
place in FLASH_regionC {section .iapMem};
place in FLASH_regionB {ro};

Прежде чем так утверждать, покажите, что у вас
section .iapMem
участвует в статистике, да еще и как readonly memory

Цитата(jcxz @ May 16 2016, 13:57) *
Не знаю кем она у Вас там затирается, но у меня в разных проектах почему-то не затирается.

Хотел бы я так.... Но вот незадача - все переменные, в т.ч. и константы, объявленные вне тела функции, по-умолчанию идут инициализированные в 0x00

define symbol __ICFEDIT_region_ROM_start__ = 0x080000EC;
define symbol __ICFEDIT_region_ROM_end__ = 0x08003FFF;
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
define block NVR with alignment = __NVRAM_page_size__,
size = __NVRAM_page_size__ * __ICFEDIT_region_NVRAM_pages__ { section NVRAM };
"NVRAM" : place at end of ROM_region { block NVR };

---
#pragma location = "NVRAM"
const char NVRAM_PLACE[2048];

*.map:
"NVRAM": 0x800
NVR 0x08003800 0x800 <Block>
NVRAM const 0x08003800 0x800 drv_NVRAM.o [1]
- 0x08004000 0x800

размер бинарника 16384, в конце нули
---
#pragma location = "NVRAM"
__no_init const char NVRAM_PLACE[2048];

*.map:
"NVRAM": 0x800
NVR 0x08003800 0x800 <Block>
NVRAM uninit 0x08003800 0x800 drv_NVRAM.o [1]
- 0x08004000 0x800

размер бинарника 16384, в конце нули
---
#pragma location = "NVRAM"
__no_init const char NVRAM_PLACE[2048];
+
*.icf
do not initialize { section NVRAM };

"NVRAM": 0x800
NVR 0x08003800 0x800 <Block>
NVRAM uninit 0x08003800 0x800 drv_NVRAM.o [1]
- 0x08004000 0x800

размер бинарника равен размеру кода.

но, к слову, во всех 3-х случаях NVRAM_PLACE оказался в статистике в readonly data.
осталось заставить компилятор! выдирать переменные из icf....
desh
Цитата(Alechek @ May 16 2016, 15:00) *
Вышлю ящик пива тому, кто скомпилит


:-). IAR ARM 7.40.5
Alechek
Цитата(desh @ May 16 2016, 17:08) *
:-). IAR ARM 7.40.5

Не считается. EEPROM не находится в "нужном регионе памяти", а выделяется динамически в стеке.
desh
Цитата(Alechek @ May 16 2016, 15:24) *
Не считается. EEPROM не находится в "нужном регионе памяти", а выделяется динамически в стеке.


Этого не было в ТЗ laughing.gif
jcxz
Цитата(Alechek @ May 16 2016, 18:00) *
Прежде чем так утверждать, покажите, что у вас
section .iapMem
участвует в статистике, да еще и как readonly memory

Какая такая "статистика"? Если имеете в виду "MODULE SUMMARY" из map-файла, то можете вынести объявление этого массива в отдельный файл и в "MODULE SUMMARY" будет отдельная строчка для него - не перепутаете.

Цитата(Alechek @ May 16 2016, 18:00) *
Хотел бы я так.... Но вот незадача - все переменные, в т.ч. и константы, объявленные вне тела функции, по-умолчанию идут инициализированные в 0x00

Учите матчасть:
do not initialize {section .iapMem};
в icf-файле. И получите:
Код
"P2":                                      0x8000              
  .iapMem             uninit   0x00078000  0x8000  iap.o [1]  
                             - 0x00080000  0x8000


Цитата(Alechek @ May 16 2016, 11:21) *
Неудобно, что EEPROM_SIZE из icf файла взять не получится. Надо будет конфигурировать память в 2-х местах.

EEPROM_SIZE нужно объявить в обычном хидере. Зачем оно в icf?
Alechek
Цитата(jcxz @ May 17 2016, 07:18) *
Какая такая "статистика"? Если имеете в виду "MODULE SUMMARY" из map-файла, то можете вынести объявление этого массива в отдельный файл и в "MODULE SUMMARY" будет отдельная строчка для него - не перепутаете.

Такая. В самом конце *.map файла. Я по ней ориентируюсь, сколько еще ресурсов осталось.
Код
  13 172 bytes of readonly  code memory
   2 322 bytes of readonly  data memory
   2 961 bytes of readwrite data memory



Цитата(jcxz @ May 17 2016, 07:18) *
Учите матчасть:
do not initialize {section .iapMem};

См выше. Уже изучено.


Цитата(jcxz @ May 17 2016, 07:18) *
EEPROM_SIZE нужно объявить в обычном хидере. Зачем оно в icf?

Затем что
Цитата(Alechek @ May 16 2016, 10:21) *
Неудобно, что EEPROM_SIZE из icf файла взять не получится. Надо будет конфигурировать память в 2-х местах.

То есть положение и размер задаем в *.icf. И дополнительно размер в *.h. Что, на мой взгляд, является избыточным действием.
Чего я и пытаюсь избежать. Сохранив при этом статистическую информацию по использованию памяти.
jcxz
Цитата(Alechek @ May 17 2016, 10:43) *
То есть положение и размер задаем в *.icf. И дополнительно размер в *.h. Что, на мой взгляд, является избыточным действием.
Чего я и пытаюсь избежать. Сохранив при этом статистическую информацию по использованию памяти.

В icf задаётся не размер. Задаётся регион куда линковать. Достаточный для данной секции/секций. Если не хватит места - линкер ругнётся.
EEPROM_SIZE не нужен в icf.
Собственно также как и при размещении других секций (кода, данных и т.п). Вы же задавая секцию кода не говорите, что задаёте размер кода и не удивляетесь что для неё надо дополнительно задавать размер, хотя можно и по коду посчитать?
А регион в icf задаётся главным образом исходя из границ регионов стирания.
Alechek
В том то и дело, что EEPROM_SIZE привязан к размеру сколько можно стереть за 1 раз. И это процессорозависимо также, как и регион расположения этой области.
А еще, для нормального функционирования необходимо как минимум 2 минимально стираемых блока.
Исходя из всего этого, считаю нецелеобразным выносить такие настройки в заголовочник.
У меня код гуляет из проекта в проект, лишние настройки - лишние проблемы. А *.icf уж точно у каждого проекта свой.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.