Setting Variables/Functions to specific memory

cancel
Showing results for 
Search instead for 
Did you mean: 

Setting Variables/Functions to specific memory

952 Views
Senior Contributor I

Following these NXP community examples (Placing Data into different RAM Blocks from Placing Functions into RAM Blocks) seems to work (compile) - but the MCUXpresso IDE is giving warnings - indicating that maybe the MCUXpresso Indexer can't find the header.

Code example:  

#include <cr_section_macros.h>

__DATA(RAM2) unsigned char array[]={

   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

   0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00,

};

 

Warnings:

Unresolved inclusion: <cr_section_macros.h>

And syntax error on the array variable.

I've tried:

1. Cleaning & rebuilding project

2. Right clicking the project in MCUXpresso -> Index -> Rebuild, Freshen, Update, Re-resolve, Search for unresolved

But I couldn't get rid of the yellow warning errors from indexer, even tho no problems show up @ build time in the Problems window. 

So my questions are: 

1. How do I get rid of the above indexing errors so I don't have all code highlighted w/ yellow?

2. Are the above 2 referenced NXP Community articles (for LPCXpresso) also valid for the RT1015 in MCUXpresso?

Thanks!

Labels (1)
15 Replies

193 Views
Senior Contributor IV

193 Views
Senior Contributor I

Thanks for the quick response, but unfortunately still no dice for the above includes after going to preferences and updating indexer settings (heuristics / use active build) as per the article you mentioned converse‌. 

Could this be specific to trying to use the cr_section_macros.h mentioned in an LPCXpresso article for an MCUXpresso iMX project?

0 Kudos

193 Views
NXP Employee
NXP Employee

Hi variable_andrew

cr_section_macros.h is an MCUXpresso IDE include, so it doesn't depend in the device that you have. I have included this library cr_section_macros.h in the sdk example "gpio_led_output.c" and I added the code of the array that you have, and I can see that it was successfully mapped to the RAM2 section. Does the __DATA(RAM2) instruction fail in the code that you have?


Have a great day,
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!
-------------------------------------------------------------------------------

193 Views
Senior Contributor I

Hi jorgeantonioalcala‌,

I've tried what you suggested as well and that's working  - for the most part, but... 

What I'm seeing is that the array is allocated in both its original destination and in the specified destination. 

ie - if I make the array have 100 elements - 100 bytes will be added to both DTC and ITC in the case where memory output looks like this:

Memory region         Used Size  Region Size  %age Used

        SRAM_DTC:       24180 B        32 KB     73.79%

        SRAM_ITC:         600 B        32 KB      1.83%

         SRAM_OC:          0 GB        64 KB      0.00%

     BOARD_FLASH:          0 GB        16 MB      0.00%]

How would I make it so that the memory isn't used in the old region, only in the new region?

Thanks!

-Andrew

0 Kudos

193 Views
Senior Contributor IV

As your array has initialised values, those values have to be placed into your code area so that (on reset) those values can be copied into your array. There is no way around this, unless you don’t provide initial values.

193 Views
Senior Contributor I

Hi converse

Thanks for the clarification - according to the below, I should be able to place the array .text into a specific memory section instead?

Placing code/rodata into different FLASH blocks 

Using code such as:

__RODATA(Flash2) const int roarray[] = {10,20,30,40,50};

I've tried this (with the suggested gpio_led_output demo:

__RODATA(RAM2) static const unsigned char array[]={

  0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00,

  0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00,

  0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00,

  0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00,

};

If I use static const - i don't see memory allocated for this array anywhere.

If I use volatile, the RAM2 destination is ignored..

Any idea as to why I wouldn't see any apparent allocation when using __RODATA with static const vs volatile ignoring the specifier?

0 Kudos

193 Views
Senior Contributor IV

If you data is not used in your program (i.e. nothing references the array), then the linker will discard it. So, if you want to check something like this. make sure your code references the array.

If you look in the .map file created by the linker, you will see a section called "Discarded input sections" and you will see what the linker has discarded as it is not used.

You haven't explained how you are using the array, but I suspect that you want to make it const.

0 Kudos

193 Views
Senior Contributor I

gotcha converse‌ - thanks. 

My usage of array is basically a bitmap of fonts for a TFT display - so it is going to be const. 

If I make sure to use the array in the gpio test - as you said - it gets allocated - tho the __RODATA bit is ignored - so it's still placed in the default location instead of... RAM2 for example. 

0 Kudos

193 Views
Senior Contributor IV

I’m a bit confused by your use case. Perhaps you can explain?

you see I am confused. You have an initialised const array that you want to place in RAM. This means you have to have the data to initialise it stored elsewhere. You may as well just store it in flash and use it directly from there.

0 Kudos

193 Views
Senior Contributor I

Hi converse‌, 

Currently I'm executing the application from SRAM, not XIP from Flash, so I'm trying to maximize my use of on chip memory. 

If my application's small enough to fit in RAM using various spaces, it seemed like the most performant way to move forward... assuming I can fully utilize all the areas of RAM

0 Kudos

193 Views
Senior Contributor IV

OK, I think I understand what you are doing.

So, at the moment, you are using the debugger to load your application into RAM. Is this correct? When you have finished development, how are you planning to deliver the application? I assume you are going to put it into Flash and then copy it from there into RAM? How are you planning to do this? This is really, really important to know, as it affects how you place code and data in your application (see below)

Back to your latest 'issue'. You are trying to place RODATA (that is, initialised, const, data) into RAM. The linker/link scripts know that this makes no sense - for it to be placed into RAM, it is going to have to be initialised, and the only place to put that initialisation data is in code (the text section) and therefore you would end up with two copies of the data - one in the code (which will be used once, to copy into RAM) and one in the RAM - which is pointless.

193 Views
Senior Contributor I

converse‌, 

That's correct that I'm currently debugging completely in RAM. 

As I understand from here https://community.nxp.com/message/1198211  NAND Flash doesn't support XIP....? 

So the end goal/hope is to boot the application from (NAND) FLASH, with the code/data allocated to RAM - (the bootloader copies the full application (.text/.data/etc) into RAM and then executes). 

Back to the original question/resp - if I'm setting array to __DATA(RAM2) - you're saying that initialized data values are somehow becoming considered .text as well? 

Wouldn't the compiler take the initialized array and put that into the appropriate .data section as initialized data?

And then when accessing said array - it goes to the data section to get the contents without needing to do extra alloc as the space is already alloced in data? It's not like I'm declaring two arrays and then copying one array to the other at runtime?

So going back to your post above - 

As your array has initialised values, those values have to be placed into your code area so that (on reset) those values can be copied into your array

On reset - wouldn't the bootloader run and copy the initialized data section from FLASH into RAM?

I don't see why using .text would have anything to do with the bootloader re-running and moving the initialized data into RAM?

Looking at the .map file - when using __DATA(RAM2) - the array symbol is put in the right place - RAM2. 

In the RAM1 section, there isn't any explicit allocation, but after the end of code - it leaves a space the same size as the array between the end of .text and the start of .reserved / .uninit_RESERVED as per this screen shot:

Screen Shot 2019-08-30 at 4.18.19 PM.png

0 Kudos

193 Views
Senior Contributor IV

I'm not familiar with the boot process for the iMX1015 part, so I can't comment on what the boot loader will or will not do.

Regarding your question about loading the initial values into the array - it is your application that does this, automatically. The linker and the startup code does this for you - you do not do anything, but the code and the data are there to do it for you. This is why you have this reserved space at the end of the .text section - to contain the array's initial values.

193 Views
Senior Contributor I

Hi converse‌, 

So if someone wanted to reduce memory usage in the main section of RAM (where .text is located) by moving a predefined array (such as this fonts array) to a different section, is there a recommended way to do this?

Is there any way to have the data values loaded directly via the loader?

It seems even when I create functions set to specific RAM blocks - as per Placing specific functions into RAM blocks  - the memory again gets doubled (used in RAM for .text, and then again in the newly specificed RAM block). 

0 Kudos

193 Views
Senior Contributor IV

I feel we are going round in circles here.

I do not think there is any way for you to do what you think you want. The linker 'knows' that RAM-based data needs to be initialised, and the only way to do that is to place that initialisation data into the code.

If you have constant data, define it a 'const' and the compiler/linker will place it with your code and will not create two copies of it. Otherwise, you will get two 'copies' - one with the initial values and the other that is used in your application.

You keep referring to a 'loader'. on MCU's this is a simple bootloader that can copy a simple block of data load the stack and jump to the entry point. That's it. Do not confused this with an application loader in a full-blown operating system (Linux, Windows etc) where it reads the executable file and can do lots a clever things with mapping data, loading RAM etc.