[En-Nut-Discussion] Global variables and threads

Harald Kipp harald.kipp at egnite.de
Tue Sep 20 09:58:52 CEST 2005


Hello Anton,

At 14:10 19.09.2005 +0000, you wrote:
>Hi all,
>
>My problem:
>My program crashes at random intervals.  In the one instance I allocate a 2k
>stack for a thread and the crash happens almost instantly upon startup.  If
>I allocate 1k for the same thread's stack the system runs quite happily.  In
>both cases NutHeapAvailable() indicate that I have > 10K memory available.
>The one thing I realize that could be a potential problem is that I use
>large global structs (approx. 3.8K)

Looks like a typical memory corruption problem to me, caused
by overwriting.



>Questions:
>I have read all the documents I could find, but I am still not clear on how
>global variables are treated by Nut/OS.
>
>1) Are global variables copied into a threads stack space when the thread is
>started, or do they simply occupy the space in which they were allocated
>upon startup for all threads to share?

Global variables are not treated by Nut/OS, but by the compiler.
You can check the .map (GCC) or .mp (ICC) for their sizes and
_fixed_ memory locations. The _rest_ of the RAM is used for the
heap, from which thread stacks are allocated.


>2) Can I assign thread stack sizes of any size (up to 28K), permitted the
>memory is available?

Yes.


>3) Does the main thread (that spawns other threads) require a larger stack
>than any other individual stack in order to spawn that new threads stack?

No, each thread occupies its own stack from available _global_
heap memory.


>4) I use fgetc() to capture uart0 and uart1 in two seperate threads, each
>having a stack of 1K, each stack accesses global arrays of 350K+350K in
>total.  I have read that when an interrupt occurs the interrupt will use the
>threads stack space.  Does this apply to fgetc()?  Does this mean that if
>the interrupt occurs at a time when the I am in a small thread such as Idle
>(384 byte stack) that I will face a memory overrun?

What do you mean by 350K? 350 kByte? Probably not. But, just
in case: Even with Ethernut 2 and its 512 kByte RAM chip, the
compiler sees 32 kByte only. The remaining 480 kByte are banked
and had to be accessed in a special way, via the PNUT file
system for example.

Interrupts may occur at any time, but they typically use far
less than 100 bytes of stack.


>P.S.
>I open my uart as follow:
>
>NutRegisterDevice(&devUsartAvr0, 0, 0); Usart0FilePtr = fopen("uart0",
>"w+"); _ioctl(_fileno(Usart0FilePtr), UART_SETSPEED, &commsBaud);
>_ioctl(_fileno(Usart0FilePtr), UART_SETCOOKEDMODE, &cookedMode);
>
>The above code transmits one char, apparently a zero.  Any idea on how to
>stop this from happening (I set my baud to 9600)?

The UART_SETCOOKEDMODE is not portable. Better use
fopen("uart0", "w+") for cooked and fopen("uart0", "w+b")
for pure binary I/O.

That code should not transmit anything. The UART transmitter
is fully interrupt driven and roughly works like this:

a) An application fills the transmit buffer by using fputs,
fprintf or similar.

b) As soon as the buffer is filled or a flush is called by the
application, the first buffered character will be put into the
UART transmit register and transmit interrupts are enabled.

c) When the character had been fully transmitted, an interrupt
occurs and the next character is moved from the buffer to the
UART transmit register. While this happens in the background,
the application may continue to fill the transmit buffer.

d) When all characters had been transmitted, transmit interrupts
are disabled again.

Keep in mind, that this is simplified.

Regards,
Harald







More information about the En-Nut-Discussion mailing list