Jump to content

    

LPCXpresso

Может кто подскажет, как сказать линковщику, что есть внешняя RAM?

Использую LPCXpresso 7.9.0.

В настройках проекта (MCU setting) добавил соответствующую секцию, но не помогает.

При линковке сообщение, что не хватает внутреннего ОЗУ... Во внешнее линковать и не пытается.

Share this post


Link to post
Share on other sites
Может кто подскажет, как сказать линковщику, что есть внешняя RAM?

Использую LPCXpresso 7.9.0.

В настройках проекта (MCU setting) добавил соответствующую секцию, но не помогает.

При линковке сообщение, что не хватает внутреннего ОЗУ... Во внешнее линковать и не пытается.

Гуглить "скрипт линкера".

Share this post


Link to post
Share on other sites
Гуглить "скрипт линкера".

 

Да я понимаю, что смотреть надо *.ld файлы. Но там все регионы памяти прописаны (формируются автоматически по настройкам из GUI и их редактировать нет смысла). Кажется должно было бы все работать. Да и описания синтаксиса я не нашел, поэтому не все в них понятно (здесь какой-то свой формат).

И такая проблема не только с внешней памятью. Я работаю с LPC4357, у него несколько банков внутреннего ОЗУ. Есть даже два смежных банка, но по мере заполнения первого, данные не "переползают" во второй. Линковщик просто ругается, что не достаточно места в первом.

На сайте указано, как код, константы, как массив переменных положить в нужный банк ОЗУ при помощи __attribute__ ((section.... Но это все не то.

С LPCXpresso (Eclipse) только начал работать, более привычен Keil. В нем примерно также в GUI указывается распределение памяти и все работает прозрачно для программиста.

А здесь даже не знаю куда ткнуться.

Share this post


Link to post
Share on other sites
Есть даже два смежных банка, но по мере заполнения первого, данные не "переползают" во второй. Линковщик просто ругается, что не достаточно места в первом.

ЕМНИП, гнутый линкер не умеет раскидывать по разным банкам. И RealView (который в Кейле) тоже не умеет. А Яр умеет.

Share this post


Link to post
Share on other sites
ЕМНИП, гнутый линкер не умеет раскидывать по разным банкам. И RealView (который в Кейле) тоже не умеет. А Яр умеет.

 

RealView как раз и умеет. Там все на раз-два настраивается прямо через GUI Keil.

 

А если GNU не умеет, то как тогда вообще работать с банками? Мне нужно немного встроенной памяти, что-бы, как минимум, проинициализировать внешнее большое ОЗУ и уйти туда работать.

Если не умеет автоматом раскидывать, то как это сделать вручную?

 

Edited by _Mikhail_

Share this post


Link to post
Share on other sites
Если не умеет автоматом раскидывать, то как это сделать вручную?

В исходнике приписывать переменные к отдельной секции, а потом размещать её в памяти как захочется.

 

Тут еще момент, о котором я писал. Скрипты для линкера формируются автоматически данной средой (LPCXpresso) и править их в тексте смысла нет. Поэтому, даже если и знать, как выправить скрипт вручную, мне не понятно как это подсунуть IDE.

Мне такие проблемы непонятны. Я всегда делаю сборку через Makefile, ну и скрипт линкера подсовываю сам, естественно.

Share this post


Link to post
Share on other sites
формируются автоматически по настройкам из GUI и их редактировать нет смысла

Дело обстоит с точностью до наоборот - не имеет смысла использовать сгенерированный как попало скрипт. Аккуратно написать свой.

Есть даже два смежных банка, но по мере заполнения первого, данные не "переползают" во второй. Линковщик просто ругается, что не достаточно места в первом.

Ну и опишите его ОДНИМ блоком, а не так, как визард нагенерил.

 

Share this post


Link to post
Share on other sites
Дело обстоит с точностью до наоборот - не имеет смысла использовать сгенерированный как попало скрипт. Аккуратно написать свой.

 

Ну и опишите его ОДНИМ блоком, а не так, как визард нагенерил.

 

Нет. Про внутренние смежные блоки я к примеру сказал. Для первичной инициализации хватает и одной банки. Нужно много внешнего ОЗУ, а оно лежит совсем по другим адресам.

 

А про скрипты согласен. Я нашел уже нашел способ, как использовать свой. Сначала генерю автоматом для шаблона, а потом снимаю найденную галочку в настройках и можно редактировать скрипт, он перезаписываться не будет.

Теперь думаю, что там надо править...

 

В исходнике приписывать переменные к отдельной секции, а потом размещать её в памяти как захочется.

Это что ко всем переменным __attribute__ ((section... приписывать?!

Нет, ну можно, конечно, для краткости задифайнить.

Тогда проще весь стартовый код перелопатить таким образом.

Share this post


Link to post
Share on other sites
Это что ко всем переменным __attribute__ ((section... приписывать?!

Нет, ну можно, конечно, для краткости задифайнить.

Если не ошибаюсь, можно в скрипте линкера указывать имена файлов. Скажем, такие-то файлы - в один банк, остальные - в другой.

Share this post


Link to post
Share on other sites
Это что ко всем переменным __attribute__ ((section... приписывать?!

Должна быть прагма типа:

#pragma arm section ...

Указывает куда, что класть. После нее действуют указания до конца файла или до отменяющей прагмы.

Share this post


Link to post
Share on other sites
Должна быть прагма типа:

#pragma arm section ...

Указывает куда, что класть. После нее действуют указания до конца файла или до отменяющей прагмы.

К сожалению, в GCC такого не нашел (

 

Буду пока смотреть в сторону скрипта линковки

Share this post


Link to post
Share on other sites
К сожалению, в GCC такого не нашел (

 

Буду пока смотреть в сторону скрипта линковки

Как было сказано выше можно на регионы памяти назначать целиком единицы линковки. К примеру всё из startup.o размещать во внутренней памяти а всё остальное во внешней.

Share this post


Link to post
Share on other sites
Как было сказано выше можно на регионы памяти назначать целиком единицы линковки. К примеру всё из startup.o размещать во внутренней памяти а всё остальное во внешней.

Ну мне это и надо. Я хочу регионом по умолчанию сделать внешнюю память (это работает), а модули стартапа через скрипот линкера разместить во внутренней RamLoc32 (не получается). Изучал LD, но пока не разобраться. Не понял, как прописать расположение данных для конкретных файлов в скрипты LPCXpresso.

Вот что сгенерила IDE:

/*
* GENERATED FILE - DO NOT EDIT
* © Code Red Technologies Ltd, 2008-2013
* © NXP Semiconductors 2013-2015
* Generated linker script file for LPC4357
* Created from memory.ldt by FMCreateLinkMemory
* Using Freemarker v2.3.23
* LPCXpresso v7.9.2 [build 493] [2015-09-14]  on 23.09.2015 9:05:06
*/

MEMORY
{
 /* Define each memory region */
 MFlashA512 (rx) : ORIGIN = 0x1a000000, LENGTH = 0x80000 /* 512K bytes (alias Flash) */  
 RAM_EXT (rwx) : ORIGIN = 0x28000000, LENGTH = 0x1000000 /* 16M bytes (alias RAM) */  
 RamLoc32 (rwx) : ORIGIN = 0x10000000, LENGTH = 0x8000 /* 32K bytes (alias RAM2) */  
}

 /* Define a symbol for the top of each memory region */
 __base_MFlashA512 = 0x1a000000 ; /* MFlashA512 */  
 __base_Flash = 0x1a000000; /* Flash */  
 __top_MFlashA512 = 0x1a000000 + 0x80000; /* 512K bytes */  
 __top_Flash = 0x1a000000 + 0x80000; /* 512K bytes */  
 __base_RAM_EXT = 0x28000000 ; /* RAM_EXT */  
 __base_RAM = 0x28000000; /* RAM */  
 __top_RAM_EXT = 0x28000000 + 0x1000000; /* 16M bytes */  
 __top_RAM = 0x28000000 + 0x1000000; /* 16M bytes */  
 __base_RamLoc32 = 0x10000000 ; /* RamLoc32 */  
 __base_RAM2 = 0x10000000; /* RAM2 */  
 __top_RamLoc32 = 0x10000000 + 0x8000; /* 32K bytes */  
 __top_RAM2 = 0x10000000 + 0x8000; /* 32K bytes */

 

/*
* GENERATED FILE - DO NOT EDIT
* © Code Red Technologies Ltd, 2008-2013
* © NXP Semiconductors 2013-2015
* Generated linker script file for LPC4357
* Created from linkscript.ldt by FMCreateLinkLibraries
* Using Freemarker v2.3.23
* LPCXpresso v7.9.2 [build 493] [2015-09-14]  on 23.09.2015 9:05:06
*/

INCLUDE "dc_freertos_webserver_Debug_library.ld"
INCLUDE "dc_freertos_webserver_Debug_memory.ld"

ENTRY(ResetISR)

SECTIONS
{
/* MAIN TEXT SECTION */
.text : ALIGN(4)
{
	FILL(0xff)
	__vectors_start__ = ABSOLUTE(.);
	KEEP(*(.isr_vector))
	/* Global Section Table */
	. = ALIGN(4); 
	__section_table_start = .;
	__data_section_table = .;
	LONG(LOADADDR(.data));
	LONG(	ADDR(.data));
	LONG(  SIZEOF(.data));
	LONG(LOADADDR(.data_RAM2));
	LONG(	ADDR(.data_RAM2));
	LONG(  SIZEOF(.data_RAM2));
	__data_section_table_end = .;
	__bss_section_table = .;
	LONG(	ADDR(.bss));
	LONG(  SIZEOF(.bss));
	LONG(	ADDR(.bss_RAM2));
	LONG(  SIZEOF(.bss_RAM2));
	__bss_section_table_end = .;
	__section_table_end = .;
	/* End of Global Section Table */

	*(.after_vectors*)

} >MFlashA512

.text : ALIGN(4)	
{
	*(.text*)
	*(.rodata .rodata.* .constdata .constdata.*)
	. = ALIGN(4);
} > MFlashA512
/*
 * for exception handling/unwind - some Newlib functions (in common
 * with C++ and STDC++) use this. 
 */
.ARM.extab : ALIGN(4) 
{
	*(.ARM.extab* .gnu.linkonce.armextab.*)
} > MFlashA512
__exidx_start = .;

.ARM.exidx : ALIGN(4)
{
	*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > MFlashA512
__exidx_end = .;

_etext = .;

/* DATA section for RamLoc32 */
.data_RAM2 : ALIGN(4)
{
	FILL(0xff)
	PROVIDE(__start_data_RAM2 = .);
	*(.ramfunc.$RAM2)
	*(.ramfunc.$RamLoc32)
	*(.data.$RAM2*)
	*(.data.$RamLoc32*)
	. = ALIGN(4);
	PROVIDE(__end_data_RAM2 = .);
 } > RamLoc32 AT>MFlashA512

/* MAIN DATA SECTION */
.uninit_RESERVED : ALIGN(4)
{
	KEEP(*(.bss.$RESERVED*))
	. = ALIGN(4);
	_end_uninit_RESERVED = .;
} > RAM_EXT
/* Main DATA section (RAM_EXT) */
.data : ALIGN(4)
{
   FILL(0xff)
   _data = .;
   *(vtable)
   *(.ramfunc*)
   *(.data*)
   . = ALIGN(4);
   _edata = .;
} > RAM_EXT AT>MFlashA512
/* BSS section for RamLoc32 */
.bss_RAM2 : ALIGN(4)
{
   PROVIDE(__start_bss_RAM2 = .);
   *(.bss.$RAM2*)
   *(.bss.$RamLoc32*)
   . = ALIGN (. != 0 ? 4 : 1); /* avoid empty segment */
   PROVIDE(__end_bss_RAM2 = .);
} > RamLoc32 
/* MAIN BSS SECTION */
.bss : ALIGN(4)
{
	_bss = .;
	*(.bss*)
	*(COMMON)
	. = ALIGN(4);
	_ebss = .;
	PROVIDE(end = .);
} > RAM_EXT
/* NOINIT section for RamLoc32 */
.noinit_RAM2 (NOLOAD) : ALIGN(4)
{
   *(.noinit.$RAM2*)
   *(.noinit.$RamLoc32*)
   . = ALIGN(4);
} > RamLoc32 
/* DEFAULT NOINIT SECTION */
.noinit (NOLOAD): ALIGN(4)
{
	_noinit = .;
	*(.noinit*) 
	 . = ALIGN(4);
	_end_noinit = .;
} > RAM_EXT

PROVIDE(_pvHeapStart = DEFINED(__user_heap_base) ? __user_heap_base : .);
PROVIDE(_vStackTop = DEFINED(__user_stack_top) ? __user_stack_top : __top_RAM_EXT - 0);

/* ## Create checksum value (used in startup) ## */
PROVIDE(__valid_user_code_checksum = 0 - 
									 (_vStackTop 
									 + (ResetISR + 1) 
									 + (NMI_Handler + 1) 
									 + (HardFault_Handler + 1) 
									 + (( DEFINED(MemManage_Handler) ? MemManage_Handler : 0 ) + 1)   /* MemManage_Handler may not be defined */
									 + (( DEFINED(BusFault_Handler) ? BusFault_Handler : 0 ) + 1)	 /* BusFault_Handler may not be defined */
									 + (( DEFINED(UsageFault_Handler) ? UsageFault_Handler : 0 ) + 1) /* UsageFault_Handler may not be defined */
									 ) );
}

Edited by IgorKossak
[codebox] для длинного кода, [code] - для короткого!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this