Page 1 of 1

Defining large variables

Posted: Mon Feb 11, 2013 11:01 am
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?

Re: Defining large variables

Posted: Mon Feb 11, 2013 11:07 am
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.

Re: Defining large variables

Posted: Mon Feb 11, 2013 11:20 am
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" );
...
}

Re: Defining large variables

Posted: Mon Feb 11, 2013 11:29 am
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

Re: Defining large variables

Posted: Mon Feb 11, 2013 11:41 am
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.

Re: Defining large variables

Posted: Mon Feb 11, 2013 12:21 pm
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.

Re: Defining large variables

Posted: Mon Feb 11, 2013 2:53 pm
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

Re: Defining large variables

Posted: Tue Feb 12, 2013 9:23 am
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.

Re: Defining large variables

Posted: Thu Feb 14, 2013 4:19 pm
by greengene
Amen brother!