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
MAX_BUFFER_LENGTH should be MAX_CONTENT_LENGTH. Sorry for the typo. Thanks Cem
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.
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
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?
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
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.
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
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
Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
Log in with Google account
No account? Register here.