Stack problem?

tjohansen wrote on Tuesday, March 24, 2009:

Hallo

I may have some stack/heap problem!?? But im not sure.

Im using the latest FreeRTOS on my LPC2478. I have 5 tasks and they are working fine.

But know I whant to add some graphics task to my project. So I create a new task, which draw some graphics in my framebuffer in a given interval. But when the task runs, then I get an Abort exception. If I check the excpetion cause and extract the assembly where it happens, then its in the context switch rutine.

What I can see in the debugger before the exception(Keil uVision), a structure passed to a graphics function is suddenly out of scope… So when the function returns I get the data abort exception.

My guess is that maybee my stack is to small? The graphics function uses many bytes of RAM. Could that be a the cause?
If I call the graphics function from the main, before the scheduler is started, then there is no problem, but when called from the task I get an exception.

Does tasks run in supervisor mode? or user mode?

This is my stack and heap setup:

UND_Stack_Size  EQU     0x00000008
SVC_Stack_Size  EQU     0x00000400
ABT_Stack_Size  EQU     0x00000008
FIQ_Stack_Size  EQU     0x00000008
IRQ_Stack_Size  EQU     0x00000400
USR_Stack_Size  EQU     0x00000008

ISR_Stack_Size  EQU     (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size +
                         FIQ_Stack_Size + IRQ_Stack_Size)

                AREA    STACK, NOINIT, READWRITE, ALIGN=3

Stack_Mem       SPACE   USR_Stack_Size
__initial_sp    SPACE   ISR_Stack_Size

Stack_Top

;// <h> Heap Configuration
;//   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF>
;// </h>

Heap_Size       EQU     0x00000000

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limit

If I look in my Startup.s file, I do not set the user mode stack pointer? Schouldnet I do that?

; Setup Stack for each mode ----------------------------------------------------

                LDR     R0, =Stack_Top

;  Enter Undefined Instruction Mode and set its Stack Pointer
                MSR     CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit
                MOV     SP, R0
                SUB     R0, R0, #UND_Stack_Size

;  Enter Abort Mode and set its Stack Pointer
                MSR     CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit
                MOV     SP, R0
                SUB     R0, R0, #ABT_Stack_Size

;  Enter FIQ Mode and set its Stack Pointer
                MSR     CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit
                MOV     SP, R0
                SUB     R0, R0, #FIQ_Stack_Size

;  Enter IRQ Mode and set its Stack Pointer
                MSR     CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit
                MOV     SP, R0
                SUB     R0, R0, #IRQ_Stack_Size

;  Enter Supervisor Mode and set its Stack Pointer
                MSR     CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
                MOV     SP, R0
                SUB     R0, R0, #SVC_Stack_Size

                EXPORT __initial_sp
;  Enter User Mode and set its Stack Pointer
;               MSR     CPSR_c, #Mode_USR
;               IF      :DEF:__MICROLIB

  ;              EXPORT __initial_sp

   ;             ELSE

   ;             MOV     SP, R0
   ;             SUB     SL, SP, #USR_Stack_Size

    ;            ENDIF

; Enter the C code -------------------------------------------------------------

                IMPORT  __main
                LDR     R0, =__main
                BX      R0

                IF      :DEF:__MICROLIB

                EXPORT  __heap_base
                EXPORT  __heap_limit

                ELSE
; User Initial Stack & Heap
                AREA    |.text|, CODE, READONLY

                IMPORT  __use_two_region_memory
                EXPORT  __user_initial_stackheap
__user_initial_stackheap

                LDR     R0, =  Heap_Mem
                LDR     R1, =(Stack_Mem + USR_Stack_Size)
                LDR     R2, = (Heap_Mem +      Heap_Size)
                LDR     R3, = Stack_Mem
                BX      LR
                ENDIF

                END

/Thomas

anonymous wrote on Tuesday, March 24, 2009:

[sorry if this looks obvious to most of you, but I’ve seen this error happen quite often in multitasked programs]

Thomas,

make sure you do not create large structures on the stack. For example, if your graphic routine uses

void vGraphicTask(void *pvParameters)
{
   unsigned char img[320*240];
   …
}

then the "img" array will be allocated onto your task stack. If you have no reentrancy issue, i.e. only one instance of the above function will run, then you better use

  static unsigned char img[320*240];

(prefix by "static")

In this case, "img" is similar to a global variable (allocated in the ".bss" section in a location statically determined at link time) whose visibility is restricted to the function in which it is declared.

davedoors wrote on Tuesday, March 24, 2009:

Also see this thread about which stacks are needed http://sourceforge.net/forum/forum.php?thread_id=3132196&forum_id=382005 (user/system stack is not required to be setup in the start up code) and these pages about stack overflows http://www.freertos.org/Stacks-and-stack-overflow-checking.html http://www.freertos.org/uxTaskGetStackHighWaterMark.html

tjohansen wrote on Tuesday, March 24, 2009:

Samuel

Thanks for the reponds. I have checked my chain of function call and the structures used are declared static. The static structure is then passed as parameter to the next function. In this function then the parameter suddenly is "out of scope"

Could i try increasing the stack size, to see if that helps me?

I have tried making other changes. In the function I declare a local variable, where I copy the static structure too instead. The structur is only 14 bytes in size.
But still. As soon as I return from the function I get an abort exception!!!..

Here is the function that failes. Its called from a task. The parameter is declared static.

static unsigned long GetCharNdx( FontRecPtr Font)
{

  unsigned long CharNdx,CharNdx1,CharNdx2;

  …
  …
 
  do
  {
      …
      …
      if (CharNdx1 == CharNdx2)
        return (Font->FirstCharNdx); <- Exception
      …
      …
  }
  while (1);
}

If I look at my abort exception (R14) and extract the cause of the location its in the following program address 0x000AD60:
      portRESTORE_CONTEXT                         ; Restore the context of the highest 
0x0000AD58  E59F0028  LDR       R0,[PC,#0x0028]
0x0000AD5C  E5900000  LDR       R0,[R0]
0x0000AD60  E590E000  LDR       R14,[R0] 0x0000AD64  E59F0020  LDR       R0,[PC,#0x0020]
0x0000AD68  E8BE0002  LDMIA     R14!,{R1}
0x0000AD6C  E5801000  STR       R1,[R0]
0x0000AD70  E8BE0001  LDMIA     R14!,{R0}
0x0000AD74  E16FF000  MSR       SPSR_cxsf,R0
0x0000AD78  E8DE7FFF  LDMIA     R14,{R0-R14}^
0x0000AD7C  E1A00000  NOP      
0x0000AD80  E59EE03C  LDR       R14,[R14,#0x003C]
0x0000AD84  E25EF004  SUBS      PC,R14,#0x00000004
0x0000AD88  40000C04  DD        0x40000C04
0x0000AD8C  40000C38  DD        0x40000C38
0x0000AD90  0000265C  DD        0x0000265C
0x0000AD94  00001E8C  DD        0x00001E8C
0x0000AD98  E0004000  DD        0xE0004000

Any idea?

tjohansen wrote on Wednesday, March 25, 2009:

Hi

I have done some more debuging. My grasphics function are some function calling a function, that calls another function etc. Is there a limit on how deep function call can be with RTOS?

I also have added the configCHECK_FOR_STACK_OVERFLOW flag. If I set to "1" I dont get any vApplicationStackOverflowHook call. But when set to "2" the hook function get called and the debugger stopps. The parameters passed to the function are corrupted.

So could the function them self cause a overflow?
Is it possible to increase the used heap size used for the tasks stack?? Would that solve the problem?

My current heap is configured to 13*1024:

#define configMINIMAL_STACK_SIZE    ( ( unsigned portSHORT ) 104 )
#define configTOTAL_HEAP_SIZE        ( ( size_t ) 13 * 1024 )

/Thomas

sotd wrote on Wednesday, March 25, 2009:

why not you just increase the stack given to the task when you create task using xTaskCreate?

tjohansen wrote on Wednesday, March 25, 2009:

Thanks sotd… that did it!!!

and by the way… DOOOOOHHH :slight_smile: