EmbDev.net

Forum: ARM programming with GCC/GNU tools Interesting problem with WinARM


Author: Cem Eryasar (cemer)
Posted on:

Rate this post
0 useful
not useful
Hello all

I am having a strange problem with my project. All coding was done in
pure C usin the WınARM toolset. Everything runs perfectly until I
increase the size of an temporary buffer, a char array. It builds fine
in both cases, but when it is increased the runtime behaviour is totally
different, i.e. usually resets, if it does not, wrong values all around.

Here is the code part:

void function1()
{
...
    swich ()
    {
       case ...:

            uint32_t temp_read_ptr = *read_ptr;
            uint32_t i;
            char temp_buffer[MAX_BUFFER_LENGTH] _attribute_ ((aligned
(4)));
            for (i = 0; i<g_ContentLength; i++)
            {
                temp_buffer[i] = buffer[temp_read_ptr];
                temp_read_ptr = (temp_read_ptr + 1) % buffer_size;
            }
            function2(temp_buffer, i);
            break;
    }
...
}

when the MAX_CONTENT_LENGTH is 512 or below everything is perfect. When
I increase that to 1024 the problem becomes visible when this piece of
code is executed.

Any ideas why this is happening?

Thanks
Cem

Author: Cem Eryasar (cemer)
Posted on:

Rate this post
0 useful
not useful
MAX_BUFFER_LENGTH should be MAX_CONTENT_LENGTH. Sorry for the typo.
Thanks
Cem

Author: Stefan (Guest)
Posted on:

Rate this post
0 useful
not useful
char temp_buffer[] is created on the stack. Are you sure the stack is
big enough to support char temp_buffer[>512]? You won't get a warning
about stack overflow! Try to check the code with char temp_buffer[] as
static DATA or BSS array.

Author: Cem Eryasar (cemer)
Posted on:

Rate this post
0 useful
not useful
Stefan wrote:
> char temp_buffer[] is created on the stack. Are you sure the stack is
> big enough to support char temp_buffer[>512]? You won't get a warning
> about stack overflow! Try to check the code with char temp_buffer[] as
> static DATA or BSS array.

Afaik the crt0.S sets the all available memory for stack. See below. Do
I need to do anything else? Where can I monitor the stack size after the
build?
Thanks
Cem

...
        .set  UND_STACK_SIZE, 0x00000004
        .set  ABT_STACK_SIZE, 0x00000004
        .set  FIQ_STACK_SIZE, 0x00000004
        .set  IRQ_STACK_SIZE, 0X00000080
        .set  SVC_STACK_SIZE, 0x00000004
        .set  MODE_USR, 0x10            // User Mode
        .set  MODE_FIQ, 0x11            // FIQ Mode
        .set  MODE_IRQ, 0x12            // IRQ Mode
        .set  MODE_SVC, 0x13            // Supervisor Mode
        .set  MODE_ABT, 0x17            // Abort Mode
        .set  MODE_UND, 0x1B            // Undefined Mode
        .set  MODE_SYS, 0x1F            // System Mode
...

_mainCRTStartup:


// Initialize Interrupt System
// - Set stack location for each mode
// - Leave in System Mode with Interrupts Disabled
// -----------------------------------------------
        ldr   r0,=_stack
        msr   CPSR_c,#MODE_UND|I_BIT|F_BIT // Undefined Instruction Mode
        mov   sp,r0
        sub   r0,r0,#UND_STACK_SIZE
        msr   CPSR_c,#MODE_ABT|I_BIT|F_BIT // Abort Mode
        mov   sp,r0
        sub   r0,r0,#ABT_STACK_SIZE
        msr   CPSR_c,#MODE_FIQ|I_BIT|F_BIT // FIQ Mode
        mov   sp,r0
        sub   r0,r0,#FIQ_STACK_SIZE
        msr   CPSR_c,#MODE_IRQ|I_BIT|F_BIT // IRQ Mode
        mov   sp,r0
        sub   r0,r0,#IRQ_STACK_SIZE
        msr   CPSR_c,#MODE_SVC|I_BIT|F_BIT // Supervisor Mode
        mov   sp,r0
        sub   r0,r0,#SVC_STACK_SIZE
        msr   CPSR_c,#MODE_SYS|I_BIT|F_BIT // System Mode
        mov   sp,r0

Author: Stefan (Guest)
Posted on:

Rate this post
0 useful
not useful
How is _stack defined? The other values are the stack sizes for
interrupt service routines. User stack for your application is the
remaining space up to DATA and BSS section. You can see the instructions
for the memory layout of your application in the linker control script.
Which target do you use?
Did you try the program with char temp_buffer[] as global or static
array?

Author: Cem Eryasar (cemer)
Posted on:

Rate this post
0 useful
not useful
Stefan wrote:
> How is _stack defined? The other values are the stack sizes for
> interrupt service routines. User stack for your application is the
> remaining space up to DATA and BSS section. You can see the instructions
> for the memory layout of your application in the linker control script.
> Which target do you use?
> Did you try the program with char temp_buffer[] as global or static
> array?

It is defined in the linker file:

/*********************************************************************** 
/
/*  ROM.ld:  Linker Script File
*/
/*********************************************************************** 
/
ENTRY(_boot)
STACK_SIZE = 0x400;
...
  .stack ALIGN(256) :
  {
    . += STACK_SIZE;
    PROVIDE (_stack = .);
  } > RAM
...

I will increase this and check it out.
Thanks a lot.
Cem

Author: Clifford Slocombe (clifford)
Posted on:

Rate this post
0 useful
not useful
Cem Eryasar wrote:
> STACK_SIZE = 0x400;

Well there is exactly your problem 0x400 is 1024 bytes, so you will have
blown the stack. An alternative to expanding the stack to accommodate
this one temporary variable is to allocate it dynamically. If dynamic
memory allocation is not acceptable, you might declare it static, but be
cautious, the function will not then be reentrant, and the memory will
not be reusable by anything else when not in use here.

Author: Cem Eryasar (cemer)
Posted on:

Rate this post
0 useful
not useful
Clifford Slocombe wrote:
> Cem Eryasar wrote:
>> STACK_SIZE = 0x400;
>
> Well there is exactly your problem 0x400 is 1024 bytes, so you will have
> blown the stack. An alternative to expanding the stack to accommodate
> this one temporary variable is to allocate it dynamically. If dynamic
> memory allocation is not acceptable, you might declare it static, but be
> cautious, the function will not then be reentrant, and the memory will
> not be reusable by anything else when not in use here.


What exactly do you mean with dynamic allocation? malloc & free? I know
that I need to write _sbrk_r etc for them but I haven't done that yet.

Thanks
Cem

Author: Martin Thomas (Guest)
Posted on:

Rate this post
0 useful
not useful
Cem Eryasar wrote:
> Clifford Slocombe wrote:
>> Cem Eryasar wrote:
>>> STACK_SIZE = 0x400;
>>
>> Well there is exactly your problem 0x400 is 1024 bytes, so you will have
>> blown the stack. An alternative to expanding the stack to accommodate
>> this one temporary variable is to allocate it dynamically. If dynamic
>> memory allocation is not acceptable, you might declare it static, but be
>> cautious, the function will not then be reentrant, and the memory will
>> not be reusable by anything else when not in use here.
>
>
> What exactly do you mean with dynamic allocation? malloc & free? I know
> that I need to write _sbrk_r etc for them but I haven't done that yet.


Yes, I guess that is what Clifford means. The temp-buffer as in your
code is allocated on the stack. Since your stack is too small to hold
the temp-buffer (and maybe other variables already allocated by a
calling function). You have "blown" the stack as already mentioned by
Stefan and Clifford.

You have three possibilities:
(1) increase the stack size as already proposed (say 0x0800 instead of
0x0400). It's the most simple solution.

(2) make temp_buffer a "static" (add the static keyword to the
declartion). Than the buffer is allocated in the _data/bss_-section and
not on the stack. But with this the memory for the buffer will always
use RAM and not just temporarly when the function gets called. Also the
function will not be reentrant as Clifford already mentioned. So this is
not a very good solution.

(3) allocate the memory used of the buffer with malloc() before use and
"give it back to the heap" with free() when no longer needed. With this
the buffer memory will be allocated (temporarly) on the heap. Only the
pointer to the buffer (result of malloc) will use some bytes on the
stack. Yes, you need some kind of interface to the hardware for dynamic
allocation. This is the sbrk-syscall. This solution will be o.k. too but
needs a little more code. Also (if it's not a one-person hobby-project)
your company's guidelines may prohibit dynamic memory allocation in
firmware-code.

Martin Thomas

Reply

Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]




Bild automatisch verkleinern, falls nötig
Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.