Jump to content

    
Sign in to follow this  
*rust*

как разместить массив 32кБ в SRAM

Recommended Posts

Добрый день, господа!

 

Среда 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, тогда прошу уважаемых модераторов перекинуть топик туда.

 

Спасибо!

Edited by IgorKossak
Перенёс

Share this post


Link to post
Share on other sites
AT91SAM3U4E содержит всего 52кБ в двух SRAM

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

 

[0x20080000-0x20083fff]: 0x8c0c minimum (size: 0x4000)

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

И проект явно не совсем пустой - 0xc0c байт данных помимо массива.

Share this post


Link to post
Share on other sites
Вообще-то в трех.

 

Очевидно Вы имеете в виду 4кБ SRAM от NFC. Да согласен, 52кБ это с учетом SRAM от контроллера NAND flesh.

Если я правильно понимаю SRAM0 содержит 32кб, а SRAM1 16кБ. Поправьте меня если я не прав.

 

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

И проект явно не совсем пустой - 0xc0c байт данных помимо массива.

 

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

 

Хорошо, почему тогда не получается создать два массива по 16кБ? Как явным образом указать компилятору поместить первым массив в конец SRAM0, а вторым полностью занять SRAM1?

Share this post


Link to post
Share on other sites
Очевидно Вы имеете в виду 4кБ SRAM от NFC. Да согласен, 52кБ это с учетом SRAM от контроллера NAND flesh.

Если я правильно понимаю SRAM0 содержит 32кб, а SRAM1 16кБ. Поправьте меня если я не прав.

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

 

Как явным образом указать компилятору поместить первым массив в конец SRAM0, а вторым полностью занять SRAM1?

Посмотрите мануал на линкер. К сожалению, я не пользуюсь IAR'ом, поэтому подсказать не могу.

Share this post


Link to post
Share on other sites

Подумав, пришел к выводу, что должен существовать способ размещения 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");
}

 

Что писать, куда писать, на что смотреть - не понятно.

Извините, если это все очевидно.

Share this post


Link to post
Share on other sites

в скрипте линкера должны быть объявлены регионы 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];

 

Share this post


Link to post
Share on other sites
в .с

Код

#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 };

 

 

Share this post


Link to post
Share on other sites
Какая связь между этими строками?

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 };

Edited by Bulya

Share this post


Link to post
Share on other sites

Bulya, спасибо все работает как Вы писали. После перемещения кучи и переменных в RAM1, RAM0 можно использовать под свои задачи, но в моем проекте не получается разместить кучу и стат. переменные в RAM1 т.к все это занимает больше чем 16кБ. Для проверки того, что не мои действия привели к такому требуемому объему, я загрузил пример mass storage device от ATMEL, в моем проекте это должно присутствовать, и попробовал сделать так как предлагалось выше. Результат один. Куча и т.д не помещаются в RAM1. Вывод напрашивается сам собой в этом случае инициализация массива такого объема невозможна, но остались вопросы:

 

1. Почему отъедается столько памяти?

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

3. Кроме файла .map можно где-нибудь посмотреть оставшиеся ресурсы?

 

Share this post


Link to post
Share on other sites
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 и нужно смотреть на что расходуется память.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this