Why is there a __NCACHE_REGION_START and __noncachedata_start__ in the SDK loader files?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Why is there a __NCACHE_REGION_START and __noncachedata_start__ in the SDK loader files?

1,967 Views
EdSutter
Senior Contributor II

Hi,

I'm trying to understand what appears to be major over-complexity in the loader (*.ld) files that come with the SDK.

I realize there is some need for memory section labels so that the MPU can be configured by using those labels, but it seems like it is a lot more complicated than need-be.

Can someone explain the use of __NCACHE_REGION_START & __NCACHE_REGION_SIZE  vs __noncachedata_start__ & __noncachedata_start__?

The BOARD_MPUConfig() function uses teh __NCACHE_REGION_START/SIZE variables, but I've also used the "NonCachable" attribute for an Ethernet driver and it seems to work just fine; but doesn't make sense to me.

Tx,

Ed

Labels (2)
0 Kudos
6 Replies

1,816 Views
FelipeGarcia
NXP Employee
NXP Employee

Hi Ed,

 

Could you please specify the NonCachable attribute in the ethernet driver you are referring to? In MCUXpresso the Noncachable regions are defined in MCU settings of the project.

pastedImage_4.png

Best regards,

Felipe

0 Kudos

1,816 Views
EdSutter
Senior Contributor II

By the way, regarding the Ethernet driver... its one that I wrote.

0 Kudos

1,816 Views
EdSutter
Senior Contributor II

Hi,

Thanks for responding. 

For some reason I didn't get an email pinging me that you responded...

Anyway, I'm not using MCUExpresso, but at some point, MCUExpresso must create (or use) a loader (*.ld) file for final linkage.  In the armgcc version of the SDK, each example project has at least one .ld file for building in different mapped modes (run from flexspi, sdram, ram, etc...).  Anyway as far as I can tell that's the only difference.  They all seem to have the same basic labels in them.  Below is an example (1062xxxxx_ram.ld from sdk), note that there is a label for  __NCACHE_REGION_START & __NCACHE_REGION_SIZE and __noncachedata_start____noncachedata_start__.  I know that MMU initialization uses the __NCACHE... tags, but I'm not sure what the purpose of the others.

Just trying to get a good understanding of the .ld file; cause it appears to be a lot more complicated than needbe...

Thanks,

/* Entry Point */
ENTRY(Reset_Handler)

HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0x2000;
STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x2000;

/* Specify the memory areas */
MEMORY
{
m_interrupts (RX) : ORIGIN = 0x00000000, LENGTH = 0x00000400
m_text (RX) : ORIGIN = 0x00000400, LENGTH = 0x0001FC00
m_data (RW) : ORIGIN = 0x20000000, LENGTH = 0x00020000
m_data2 (RW) : ORIGIN = 0x20200000, LENGTH = 0x000C0000
}

/* Define output sections */
SECTIONS
{
__NCACHE_REGION_START = ORIGIN(m_data2);
__NCACHE_REGION_SIZE = 0;

/* The startup code goes first into internal RAM */
.interrupts :
{
__VECTOR_TABLE = .;
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} > m_interrupts

/* The program code and other data goes into internal RAM */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
} > m_text

.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > m_text

.ARM :
{
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} > m_text

.ctors :
{
__CTOR_LIST__ = .;
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
from the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__CTOR_END__ = .;
} > m_text

.dtors :
{
__DTOR_LIST__ = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
__DTOR_END__ = .;
} > m_text

.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} > m_text

.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} > m_text

.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} > m_text

__etext = .; /* define a global symbol at end of code */
__DATA_ROM = .; /* Symbol is used by startup for data initialization */

__VECTOR_RAM = ORIGIN(m_interrupts);
__RAM_VECTOR_TABLE_SIZE_BYTES = 0x0;

.data : AT(__DATA_ROM)
{
. = ALIGN(4);
__DATA_RAM = .;
__data_start__ = .; /* create a global symbol at data start */
*(m_usb_dma_init_data)
*(.data) /* .data sections */
*(.data*) /* .data* sections */
KEEP(*(.jcr*))
. = ALIGN(4);
__data_end__ = .; /* define a global symbol at data end */
} > m_data
__NDATA_ROM = __DATA_ROM + (__data_end__ - __data_start__);
.ncache.init : AT(__NDATA_ROM)
{
__noncachedata_start__ = .; /* create a global symbol at ncache data start */
*(NonCacheable.init)
. = ALIGN(4);
__noncachedata_init_end__ = .; /* create a global symbol at initialized ncache data end */
} > m_data
. = __noncachedata_init_end__;
.ncache :
{
*(NonCacheable)
. = ALIGN(4);
__noncachedata_end__ = .; /* define a global symbol at ncache data end */
} > m_data

__DATA_END = __NDATA_ROM + (__noncachedata_init_end__ - __noncachedata_start__);
text_end = ORIGIN(m_text) + LENGTH(m_text);
ASSERT(__DATA_END <= text_end, "region m_text overflowed with text and data")

/* Uninitialized data section */
.bss :
{
/* This is used by the startup in order to initialize the .bss section */
. = ALIGN(4);
__START_BSS = .;
__bss_start__ = .;
*(m_usb_dma_noninit_data)
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
__END_BSS = .;
} > m_data

.heap :
{
. = ALIGN(8);
__end__ = .;
PROVIDE(end = .);
__HeapBase = .;
. += HEAP_SIZE;
__HeapLimit = .;
__heap_limit = .; /* Add for _sbrk */
} > m_data

.stack :
{
. = ALIGN(8);
. += STACK_SIZE;
} > m_data

/* Initializes stack on the end of block */
__StackTop = ORIGIN(m_data) + LENGTH(m_data);
__StackLimit = __StackTop - STACK_SIZE;
PROVIDE(__stack = __StackTop);

.ARM.attributes 0 : { *(.ARM.attributes) }

ASSERT(__StackLimit >= __HeapLimit, "region m_data overflowed with stack and heap")
}

0 Kudos

1,816 Views
FelipeGarcia
NXP Employee
NXP Employee

Hello Ed,

 

This seems to be part of the structure of the GCC linker file. I checked the linker file in MCUXpresso and the structure is different.

 

Apart from that, if we see the __NCACHE_REGION_START is the start address of the region in physical memory. It is an expression that must evaluate to a constant before memory allocation is performed. On the other hand, __noncachedata_start__ is a global symbol that will later help define other symbols.

 

Best regards,

Felipe

0 Kudos

1,816 Views
EdSutter
Senior Contributor II

Thanks Felipe,

But they are two distinct memory sections... __NCACHE_REGION_START is m_data2, but __noncachedata_start__ is in m_data.  That's the part that confuses me.  AFAIK, MMU initialization only configures __NCACHE_REGION_START to be non-cached; but my Ethernet driver is using __noncachedata_start__ for its descriptors and it works fine despite not being non-cacheable.  There's something going on that I just don't get yet...

0 Kudos

867 Views
dcika
Contributor I

Hi,

it's an old thread, I am sure you have discovered by now that your m_data region is in the SRAM_DTC region which is directly connected to the MCU core and not going through the cache. At lest this is the case with 1050, and I guess this is why your driver was working although not specifically put in the non cacheable region.

0 Kudos