AW: [En-Nut-Discussion] Using NutOS without external SRAM?

Oliver Schulz Oliver.Schulz at bong.de
Wed May 12 10:35:58 CEST 2004


Hi Marc,

> It's all working now, with some 900 bytes heap left :)
Fine. Took me some sleepless nights, while thinking about your problem..
;-)

> 
> Thank you again for the in-depth explanation. I suppose you 
> should put this
> into the FAQ (if not already done :)
Good advise. Will talk to Harald.

> But one question is left for me:
> How should I calculate the minimal heap a thread uses?
> Take a thread with just some fgets(uart0) in a loop with an 
> bufferarray[128]
> + max. 1-2 concurrent interrupt.
> How much heap should we give the thread with NutThreadCreate ??

First we have to distinguish between heap memory and stack memory. The
heap mem can be used by any thread via reservation by 'NutHeapAlloc' or
'malloc'. The heap mem you need is not that difficult to calculate,
because on every call to NutHeapAlloc, you have to tell nut/os how many
bytes you will use. Simply add these bytes and find out the maximum at
any time in your application.
The heap mem used by NutHeapAlloc is taken from global memory, so to
speak. Upon system initalization, (nearly) all unused RAM is added to
that global memory pool, called heap.

The stack mem is some more tricky. Stack mem is used by compiler and the
atmega itself to store local variables in functions, temporary saved
registers, parameter for function calls and of course function call jump
back addresses. Normally, if you just program in C, you never see or get
in touched with the stack mem, it's totaly hidden by the compiler. But
if you want to create a new thread, you have to tell a stack size for
this thread. This stack size depends on how 'complicated' the thread is.
The more local variables are used in functions, or if you use a deep
call tree (func a calls func b, which calls func c, which calls func
d...), or using recursive functions, the more 'complicated' (= uses more
stack mem) is the thread.

Furthermore, if not using the separate interrupt stack with avr-gcc
(ver. 3.5), every time an interrupt occurs, the whole interrupt routine
uses the stack of the current thread. That means, first some registers
are saved on the current thread's stack (about 15 bytes for avr-gcc
3.4), and all subsequent stack usage in the interrupt routine burdens
the running thread's stack.

Conclusion: To evaluate the stack size for a new thread, take the
'complexity' of the new thread AND the most 'complicated' interrupt
routine into account.
Based on my experience, I found a stack size of 512 bytes is suitable
for most 'advanced' threads.

On thread creation, the new thread's stack mem is taken from the heap
mem, because the heap is the only free available ram resource. 

One hint: I using some kind of local buffers in functions, allocate them
dynamically. That means use a pointer variable and reserve memory with
NutHeapAlloc. Otherwise this buffer is taken from the stack (if not
declared as 'static'), and that could be the reason, why the system
sometimes crashes because the current stack overruns.
If you declare such buffers as 'static', the memory is fixed reserverd
by the linker, but the avaiable heap mem after system start is reduced
by this buffer size. This would be a good choice, if you ALWAYS need
this buffer. So you don't need to allocate and free it all the time,
like using it dynamically.


Regards,
Oliver.

> 
> Greetings 
> /Marc
> 
> > -----Original Message-----
> > From: en-nut-discussion-bounces at egnite.de 
> > [mailto:en-nut-discussion-bounces at egnite.de] On Behalf Of 
> > Oliver Schulz
> > Sent: Monday, May 10, 2004 2:30 PM
> > To: Ethernut User Chat (English)
> > Subject: AW: [En-Nut-Discussion] Using NutOS without external SRAM?
> > 
> > 
> > Hi Marc,
> > 
> > 
> > > So, my question is: How much RAM is minimum, if I want to use
> > > 2 buffered
> > > uarts and 2 tasks?
> > Exactly 3842 bytes... *g*
> > 
> > No, just kidding. There is really no simple answer.
> > 
> > Some points, that might help.
> > 1. If using the USART driver, you need about 410 bytes per 
> > buffered uart.
> > 2. Stack size of threads. Main's stack is 768 bytes and idle 
> > is 384 bytes. Add any additional thread stack size.
> > (Would be no bad idea, if using the main thread as worker 
> > thread. That doesn't waste its stack.)
> > 3. Any string constants used in your programm are located in 
> > static ram, unless they are declares as PROGMEM (or PCHAR).
> > (Consider using printf_P functions.)
> > 4. Some other internal variables used by Nut/OS. That are 
> > about some 30 bytes, but I'm not sure, depends on the used 
> hardware...
> > 
> > If using avr-gcc the separate irq stack can save heap mem, if 
> > you have more than two threads. There is no benefit, if 
> > having just main + idle.
> > 
> > If your linker can create a map file of the linked project, 
> > you can figure out, how much static ram your program uses. 
> > Try to reduce the static variables. 
> > The remaining ram is configured for heap by Nut/OS and is 
> > used for thread's stacks and dynamically data, like usart buffers...
> > 
> > Hope that helps a bit,
> > Oliver.
> > _______________________________________________
> > En-Nut-Discussion mailing list
> > En-Nut-Discussion at egnite.de
> > http://www.egnite.de/mailman/listinfo.cgi/en-nut-discussion
> > 
> 
> _______________________________________________
> En-Nut-Discussion mailing list
> En-Nut-Discussion at egnite.de
> http://www.egnite.de/mailman/listinfo.cgi/en-nut-discussion
> 



More information about the En-Nut-Discussion mailing list