Defining large variables

Discussion to talk about software related topics only.
Post Reply
jch
Posts: 8
Joined: Mon Jan 07, 2013 8:12 am

Defining large variables

Post by jch »

I'm using the MOD5441x and need to define an array that is fairly large, on the order of 7k bytes. Depending on where I try this, the program freezes or traps, failing to print any useful information to the screen because of a corrupt stack. Given that complaint, it seemed like stack sizes were a decent place to look. After digging a little bit I found some stack size definitions in constants.h and thought increasing MAIN_TASK_STK_SIZE would allow me to create some larger buffers. I did so and rebuilt the system files, but when I tried building my program the compiler complained about me overflowing SRAM (...section .SRAM_SECT will not fit in region SRAM...ld.exe: region SRAM overflowed by 26880 bytes). Of course the amount overflowed is more than the increase in stack size I specified so I don't really understand that...

Regardless, given the amount of RAM on this thing, there has to be a way to define huge variables. Can anyone help out?
seulater
Posts: 445
Joined: Fri Apr 25, 2008 5:26 am

Re: Defining large variables

Post by seulater »

Are you using OSTaskCreate or OSSimpleTaskCreatewName to create your tasks ?
If you use OSTaskCreate, you can define your stack size you need for that thread individually from the rest so you dont have to modify the define MAIN_TASK_STK_SIZE as that would affect all of them.
jch
Posts: 8
Joined: Mon Jan 07, 2013 8:12 am

Re: Defining large variables

Post by jch »

None of the above? This is all just in UserMain. I haven't spawned any additional tasks other than the typical startup stuff (which happens after the variable definition which can freeze the system), ie:

Code: Select all

void UserMain( void *pd )
{
	unsigned short lfm_buffer[3500]; // KABOOM

	OSChangePrio( MAIN_PRIO );
	InitializeStack();
	EnableAutoUpdate();
	EnableTaskMonitor();
	EnableSmartTraps();
	ShowIP( EthernetIP );
	iprintf( "\r\n" );
...
}
User avatar
tod
Posts: 587
Joined: Sat Apr 26, 2008 8:27 am
Location: Southern California
Contact:

Re: Defining large variables

Post by tod »

Is there a reason you don't want to just new up the array so that it's allocated on the heap?

Code: Select all

 unsigned short* lfm_buffer = new short[3500]; // No Kaboom
(Of course I would recommend you use a std::vector instead but ...)

Tod
jch
Posts: 8
Joined: Mon Jan 07, 2013 8:12 am

Re: Defining large variables

Post by jch »

No reason, really, other than I'm used to static allocation and I come from a C background. Though seulater's response made me take a look more closely into task stack allocation and it seems everything works fine if it's global. It must pull the memory from somewhere else...

So there are two solutions to the issue, at least, though it still seems like one should be able to statically create a variable of this size without it being so problematic.

Thanks for the help guys.
User avatar
tod
Posts: 587
Joined: Sat Apr 26, 2008 8:27 am
Location: Southern California
Contact:

Re: Defining large variables

Post by tod »

I think it's pretty unusual in an embedded environment to create a large data structure on the stack. Since the NB family reuses a lot of code among processors the default stack size is pretty small (typically 8-12K bytes) to accommodate the devices with less memory. When you create a task you have complete control over the stack size. It's not just arrays you have to worry about, you have to be careful about large local structures (local to both functions and ISRs), excessive function call nesting ( recursive coding can easily get you into trouble), interrupt nesting, passing parameters by value instead of reference and any other coding practice that requires stack space.

Personally I would much prefer new(ing) (or malloc(ing) if you prefer C) a structure on the stack and maintaining proper scoping of the variable, to putting it in the global memory space.
rsg
Posts: 54
Joined: Thu May 15, 2008 5:36 am

Re: Defining large variables

Post by rsg »

Right, tod.

I would also suggest noting that the OP example is an example of an auto allocated variable.

An alternate would be "true" static allocation:

Code: Select all

void UserMain( void *pd )
{
  static unsigned short lfm_buffer[3500]; // No-KABOOM
  . . .
Depends on what you need, of course. Typically, if the usage is temporary, new/free is more attractive; if it is for the lifetime of the program, then the static approach is nice, especially since you don't have to worry about allocation failures.

Large auto allocations are just not a good idea, in general; it's much harder to diagnose blown stacks than check for allocation failures (new/free) or letting the linker report errors.

Just my $0.02, adjusted for inflation and increased taxes
User avatar
dciliske
Posts: 624
Joined: Mon Feb 06, 2012 9:37 am
Location: San Diego, CA
Contact:

Re: Defining large variables

Post by dciliske »

As a general rule, you should attempt to perform as much allocation as possible in a static context as opposed to dynamic allocation. In almost all cases where you're using a NB device, you probably want 100% uptime for months or years at a time. Over that time frame even minor allocations can lead to memory fragmentation, given how little memory most of the devices have. Also, by using static allocation you can get a much better estimate of the total memory usage of your application (compcode will tell you when you build your app).

In this regard, I would prefer rsg's approach over tod's (no offense tod!). This is not to say that you shouldn't ever use it, just be aware of the potential issues. Also, as an aside, if you find yourself looking to use more C++ in embedded code, I'd listen to what tod has to say; he's one of the best out there for it.
Dan Ciliske
Project Engineer
Netburner, Inc
greengene
Posts: 164
Joined: Wed May 14, 2008 11:20 am
Location: Lakeside, CA

Re: Defining large variables

Post by greengene »

Amen brother!
Post Reply