Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: как разместить массив 32кБ в SRAM
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
*rust*
Добрый день, господа!

Среда IAR, проц. AT91SAM3U4E. Пытаюсь создать массив 32кБ (unsigned char). Пишет, что места нет, хотя проект пустой. AT91SAM3U4E содержит всего 52кБ в двух SRAM.
Пытался создать два массива по 16кБ, подумав что компилятор не может разместить целый массив 32кБ сразу в двух SRAM, но все повторилось, пишет нет места.
Error[Lp011]: section placement failed: unable to allocate space for sections/blocks with a total estimated minimum size of 0x8c0c bytes in
<[0x20080000-0x20083fff]> (total uncommitted space 0x4000).
Needed:
[0x20080000-0x20083fff]: 0x8c0c minimum (size: 0x4000)

Как решить этот вопрос?

Может вопрос не совсем по адресу и мне нужно на ветку с IAR, тогда прошу уважаемых модераторов перекинуть топик туда.

Спасибо!
aaarrr
Цитата(*rust* @ Mar 21 2011, 10:43) *
AT91SAM3U4E содержит всего 52кБ в двух SRAM

Вообще-то в трех.

Цитата(*rust* @ Mar 21 2011, 10:43) *
[0x20080000-0x20083fff]: 0x8c0c minimum (size: 0x4000)

Смотрите, что у вас написано в скрипте линкера для SRAM0 - он пытается уложить данные в 16Кб SRAM1.
И проект явно не совсем пустой - 0xc0c байт данных помимо массива.
*rust*
Цитата
Вообще-то в трех.


Очевидно Вы имеете в виду 4кБ SRAM от NFC. Да согласен, 52кБ это с учетом SRAM от контроллера NAND flesh.
Если я правильно понимаю SRAM0 содержит 32кб, а SRAM1 16кБ. Поправьте меня если я не прав.

Цитата
Смотрите, что у вас написано в скрипте линкера для SRAM0 - он пытается уложить данные в 16Кб SRAM1.
И проект явно не совсем пустой - 0xc0c байт данных помимо массива.


В проекте присутствовали две строки для вывода через DBGU, я их закоментил и все уложилось. Т.е получается, что невозможно создать буфер на 32кБ, целиком, т.к. он сможет поместиться только в SRAM0, но при резервировании даже одной переменной размер данных вылетает за предел памяти.

Хорошо, почему тогда не получается создать два массива по 16кБ? Как явным образом указать компилятору поместить первым массив в конец SRAM0, а вторым полностью занять SRAM1?
aaarrr
Цитата(*rust* @ Mar 22 2011, 22:47) *
Очевидно Вы имеете в виду 4кБ SRAM от NFC. Да согласен, 52кБ это с учетом SRAM от контроллера NAND flesh.
Если я правильно понимаю SRAM0 содержит 32кб, а SRAM1 16кБ. Поправьте меня если я не прав.

Все правильно.

Цитата(*rust* @ Mar 22 2011, 22:47) *
Как явным образом указать компилятору поместить первым массив в конец SRAM0, а вторым полностью занять SRAM1?

Посмотрите мануал на линкер. К сожалению, я не пользуюсь IAR'ом, поэтому подсказать не могу.
*rust*
Подумав, пришел к выводу, что должен существовать способ размещения 32кБ в SRAM.

1. разместить 32кБ полностью в SRAM0,
2. разместить по 16кБ в SRAM0 и SRAM1.

По первому пункту компилятор должен резервировать всю память SRAM0 для массива, а все остальные используемые переменные размещать в SRAM1 и SRAM(NFC).

По второму каким-то образом разместить массивы по 16кБ в SRAM0 и SRAM1.

Не один из вариантов у меня пока не получается.

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

Код
.//In the linker configuration file, it can look like this:
define block TempStorage with size = 0x1000, alignment = 4 { };
place in RAM { block TempStorage };
//To retrieve the start of the allocated memory from the application, the source code could
//look like this:
/* Declares a section */
#pragma section = "TempStorage"
char *TempStorage()
{
  /* Return start address of section TempStorage. */
  return __section_begin("TempStorage");
}


Что писать, куда писать, на что смотреть - не понятно.
Извините, если это все очевидно.
Bulya
в скрипте линкера должны быть объявлены регионы SRAM
Код
define region SRAM0 = Mem:[from 0x20000000  size 32K];
define region SRAM1 = Mem:[from 0x20080000  size 16K];


Цитата
1. разместить 32кБ полностью в SRAM0,

в .icf
Код
place in SRAM0  { section TempStorage };
place in SRAM1  { readwrite, block CSTACK, ... };

в .с
Код
#pragma location = "TempStorage"
unsigned char Buf[0x8000];


Цитата
2. разместить по 16кБ в SRAM0 и SRAM1.

в .icf
Код
place in SRAM0  { readwrite, block CSTACK, ...  };
place in SRAM1  { section SRAM1_data };

в .с
Код
unsigned char Buf0[0x4000];
#pragma location = "SRAM1_data"
unsigned char Buf1[0x4000];

*rust*
Спасибо, попробую разобраться. Думаю вопросы еще возникнут. rolleyes.gif
*rust*
Цитата
в .с
Код
#pragma location = "TempStorage"
unsigned char Buf[0x8000];


Какая связь между этими строками?


Делаю так по первому варианту когда 32кБ полностью пытаюсь инициализировать.

в скрипте линкера дописываю
Код
place in RAM0_region  { section TempStorage };


в .с
Код
#pragma section = "TempStorage"
unsigned char Buf[0x8000];


компилируются нормально, но если начинаешь работать с Buf[] к примеру
Код
Buf[100]=0xAA;

то все, лезут ошибки:
Error[Lp011]: section placement failed: unable to allocate space for sections/blocks with a total estimated minimum size of 0xa38f bytes in
<[0x20000000-0x20007fff]> (total uncommitted space 0x8000).
Needed:
[0x20000000-0x20007fff]: 0xa38c minimum (size: 0x8000)

Вот мой скрипт линкера:
Код
/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\a_v1_0.xml" */
/*-Vector table start*/
define symbol __ICFEDIT_vector_start__ = 0x00080000; /*Add for CMSIS*/
/*-Memory Regions-*/
define symbol __ICFEDIT_region_RAM0_start__  = 0x20000000;
define symbol __ICFEDIT_region_RAM0_end__    = 0x20007FFF;
define symbol __ICFEDIT_region_RAM1_start__  = 0x20080000;
define symbol __ICFEDIT_region_RAM1_end__    = 0x20083FFF;
define symbol __ICFEDIT_region_ROM0_start__  = 0x00080000;
define symbol __ICFEDIT_region_ROM0_end__    = 0x0009FFFF;
define symbol __ICFEDIT_region_ROM1_start__  = 0x00100000;
define symbol __ICFEDIT_region_ROM1_end__    = 0x0011FFFF;
/*-Sizes-*/
/*define symbol __ICFEDIT_size_cstack__        = 0x1000;*//*for nandflash*/
define symbol __ICFEDIT_size_cstack__        = 0x2000;
define symbol __ICFEDIT_size_heap__          = 0x200;
/*-Specials-*/
/*define symbol __ICFEDIT_region_RAM_VECT_start__ = __ICFEDIT_region_RAM0_start__;*/ /*Referenced for CMSIS*/
/*define symbol __ICFEDIT_size_vectors__          = 0x100;*/ /*Referenced for CMSIS*/
/*-Exports-*/
/*export symbol __ICFEDIT_region_RAM_VECT_start__;*/
export symbol __ICFEDIT_vector_start__; /*Add for CMSIS*/
/**** End of ICF editor section. ###ICF###*/

define memory mem with size   = 4G;
/*define region RAM_VECT_region = mem:[from __ICFEDIT_region_RAM_VECT_start__ size __ICFEDIT_size_vectors__];*/ /*Referenced for CMSIS*/
/*define region RAM0_region     = mem:[from __ICFEDIT_region_RAM0_start__+__ICFEDIT_size_vectors__ to __ICFEDIT_region_RAM0_end__];*/ /*Referenced for CMSIS*/
define region RAM0_region     = mem:[from __ICFEDIT_region_RAM0_start__ to __ICFEDIT_region_RAM0_end__];
define region RAM1_region     = mem:[from __ICFEDIT_region_RAM1_start__ to __ICFEDIT_region_RAM1_end__];
/*define region RAM_region      = mem:[from __ICFEDIT_region_RAM0_start__+__ICFEDIT_size_vectors__ to __ICFEDIT_region_RAM0_end__] |
                                mem:[from __ICFEDIT_region_RAM1_start__ to __ICFEDIT_region_RAM1_end__];*/ /*Referenced for CMSIS*/
define region ROM0_region     = mem:[from __ICFEDIT_region_ROM0_start__ to __ICFEDIT_region_ROM0_end__];
define region ROM1_region     = mem:[from __ICFEDIT_region_ROM1_start__ to __ICFEDIT_region_ROM1_end__];

/*define block RamVect   with alignment = 8, size = __ICFEDIT_size_vectors__  { };*/
define block CSTACK    with alignment = 8, size = __ICFEDIT_size_cstack__   { };
define block HEAP      with alignment = 8, size = __ICFEDIT_size_heap__     { };

initialize by copy { readwrite };
do not initialize  { section .noinit };

/*place at start of ROM0_region { readonly section .vectors };*/ /*Referenced for CMSIS*/
place at address mem:__ICFEDIT_vector_start__ { readonly section .vectors }; /*Add for CMSIS*/
place in ROM0_region          { readonly };
place in RAM0_region          { readwrite, block HEAP };
place in RAM1_region          { block CSTACK }; /* for nandflash*/
/*place in RAM_VECT_region      { block RamVect };*/ /*Referenced for CMSIS*/

//Эту строку я дописываю
place in RAM0_region  { section TempStorage };


Bulya
Цитата
Какая связь между этими строками?

pragma всегда относится к следующему за ним определению.
#pragma location задает секцию, в которую должен быть помещен определяемый объектю

Вы кроме TempStorage помещаете в RAM0_region все статические переменные и кучу
Цитата
place in RAM0_region { readwrite, block HEAP };

надо
Код
place in RAM0_region { section TempStorage };
place in RAM1_region { readwrite, block HEAP, block CSTACK };
*rust*
Bulya, спасибо все работает как Вы писали. После перемещения кучи и переменных в RAM1, RAM0 можно использовать под свои задачи, но в моем проекте не получается разместить кучу и стат. переменные в RAM1 т.к все это занимает больше чем 16кБ. Для проверки того, что не мои действия привели к такому требуемому объему, я загрузил пример mass storage device от ATMEL, в моем проекте это должно присутствовать, и попробовал сделать так как предлагалось выше. Результат один. Куча и т.д не помещаются в RAM1. Вывод напрашивается сам собой в этом случае инициализация массива такого объема невозможна, но остались вопросы:

1. Почему отъедается столько памяти?
2. Я не использую контроллер NAND flash, как можно добавить 4 кБ озу в общее пользование и как это посмотреть в файле линкера.
3. Кроме файла .map можно где-нибудь посмотреть оставшиеся ресурсы?
Bulya
Цитата
1. Почему отъедается столько памяти?

размеры стека и кучи определены в
Код
define symbol __ICFEDIT_size_cstack__        = 0x2000;
define symbol __ICFEDIT_size_heap__          = 0x200;

define block CSTACK    with alignment = 8, size = __ICFEDIT_size_cstack__   { };
define block HEAP      with alignment = 8, size = __ICFEDIT_size_heap__     { };

все остальное - статические переменные, созданные в программе

Цитата
2. Я не использую контроллер NAND flash, как можно добавить 4 кБ озу в общее пользование и как это посмотреть в файле линкера.

Код
define symbol __region_NAND_RAM_start__  = 0x20100000;
define symbol __region_NAND_RAM_end__    = 0x2010107F;

define region NAND_RAM_region = mem:[from __region_NAND_RAM_start__ to __region_NAND_RAM_end__];

Но определять какие секции должны лечь в этот регион надо в .icf самому.

Можно, например, перенести туда из RAM1_region стек и кучу:
place in NAND_RAM_region { block HEAP, block CSTACK };

или какие-то крупные объекты, которые легко выделить в отдельную секцию через #pragma location = "NAND_RAM_section"
place in NAND_RAM_region { section NAND_RAM_section };

Именно в .map и нужно смотреть на что расходуется память.
*rust*
Bulya, огромное спасибо за Вашу помощь. Надеюсь, эта информация будет полезна всем.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.