No reboot after power off/on

deboeck wrote on Sunday, April 12, 2009:

Dear,

  I’m using FreeRTOS with IAR on an lpc2364. Compiling, uploading and debugging code is no problem.

  After a power off/on cycle, however, the app doesn’t boot automatically. When I start only one task (flashing a LED), the app does boot after power off/on.

  Do you have any idea what might be going wrong?

  All your comments are appreciated!

Thanks!
Bart
 

davedoors wrote on Monday, April 13, 2009:

When you start a debugger session the C Spy debugger will run a macro file that initializes several interfaces and registers. I would guess that the macro file is initializing something during debug sessions that is otherwise not initialized by your C code.

deboeck wrote on Monday, April 13, 2009:

Thanks for the feedback!

I guess that this can be tested by uploading the app in a "no debugger session"?

Thanks,
Bart

deboeck wrote on Monday, April 13, 2009:

Uploading a release build doesn’t solve the problem.

Does anyone have a similar experience? I’m lost at this one.

Any hint is appreciated!

Thanks!
Bart

deboeck wrote on Monday, April 13, 2009:

update:

  - restart of FreeRTOS after power off/on cycle doesn’t work (neither for flash led task)
  - a standard while loop with flash led functionality does work

Settings of the IAR project are the same in both cases. So, this seems to be a FreeRTOS issue. Correct?

Am I missing some configuration options?

Please advice.

Thanks!
Bart

rtel wrote on Monday, April 13, 2009:

Are you ensuring that nothing attempts to perform a context switch until after the scheduler has been started?  This means interrupts that call any API functions must not be enabled until the scheduler is started (interrupts will become globally enabled automatically when the first task starts).

Are you initialising the interrupt controller?  Are you setting up the clocks?  It might be that the debugger is doing this for you when running a debug session.  Check what the debugger start up macros are doing and see if there is anything that you need to do in your application code.

Can you determine how far the code is getting when you run it without the debugger.  Try setting an LED just before calling vTaskStartScheduler() to see if you ever get that far.  Then try moving the point where the LED is set into the first task to see if the scheduler ever runs a task.

Also try setting an LED after the call to vTaskStartScheduler() to ensure the call does not return.

Are you using the same startup files and linker scripts between the debug and non debug builds?

Regards.

deboeck wrote on Monday, April 13, 2009:

Dear Richard,

  Thanks for the extensive answer!

  As far as I know, there are no context switches before the scheduler starts: I only initialize the board before calling vTaskStartScheduler.

  Clocks, VIC, etc. are initialised during initialization of the board.

  To determine how far the code is getting without debugger, I’ve done the following test:

    BoardInit();
    LedOn();
    vTaskStartScheduler();

After power off/on the led is not on. The following code:

    BoardInit();
    LedOn();
    while(1)
    {
    }
    vTaskStartScheduler();

does work, i.e. the led is on after power off/on.

  Something going wrong during startup?

Thanks!
Bart
 

rtel wrote on Monday, April 13, 2009:

So the code:

    BoardInit();
    LedOn();
    while(1)
    {
    }
    vTaskStartScheduler();

shows that the call to start the scheduler is being reached.  There might be something in one of the tasks that is turning the LED off again after that.

Can you create a task like this:

void vATask( void *pv )
{
____portDISABLE_INTERRUPTS();
____LedOn();
____while( 1 );
}

and create it as the highest priority task in the entire system - this will ensure it is the task that runs first.  Turning on the LED will show that the task starts to run.  Disabling interrupts first will ensure no other tasks ever run (so cannot turn the LED off again).

Regards.

deboeck wrote on Monday, April 13, 2009:

the code:

BoardInit();
LedOn();
while(1)
{
}
vTaskStartScheduler();

is run in main. BoardInit();LedOn();while(1){}; are not part of a task. I tested

main()
{
  BoardInit();
  LedOn();
  vTaskStartScheduler();
}

and

main()
{
  BoardInit();
  LedOn();
  while(1)
  {
  }
  vTaskStartScheduler();
}

The first case does not turn on the led after power off/on, the second case does.

As you requested, I’ve added the vATask. This is the only task in the system. It runs correctly in the debugger. It doesn’t run after power off/on.

deboeck wrote on Monday, April 13, 2009:

Dear Richard,

  Done a test on an Olimex LPC2378 STK board with FreeRTOS - same IAR project, same headers, same startup code, etc. FreeRTOS runs without problem on the Olimex board: led flashes after power off/on.

  What might explain this behaviour?

Thanks for all the feedback,
Bart

rtel wrote on Monday, April 13, 2009:

>As you requested, I’ve added the vATask. This is the only task in the
>system. It runs correctly in the debugger. It doesn’t run after power
>off/on.

So when running the code without the debugger vTaskStartScheduler() is being called, but the task does not run.

1) Can you ensure that you are in Supervisor mode when vTaskStartScheduler() is called.  Normally FreeRTOS aps will set the processor into supervisor mode before main() is called.

2) Can you ensure that the IRQ and SWI interrupt vectors are set correctly.

Regards.

edwards3 wrote on Monday, April 13, 2009:

Different memory interface setup? Is the debugger configuring the buses on the processor?

deboeck wrote on Monday, April 13, 2009:

Below the cstartup.s file. If I’m not mistaken, the Supervisor mode is set in

; Add more initialization here

                BIC     r0, r0, #MODE_MSK      ; Clear the mode bits
                ORR     r0, r0, #SVC_MODE       ; Set SVC mode bits
                MSR     cpsr_c, r0              ; Change the mode

/////////////////////////////cstartup.s////////////////////////////////////

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Part one of the system initialization code,
;; contains low-level
;; initialization.
;;
;; Copyright 2006 IAR Systems. All rights reserved.
;;
;; $Revision: 21638 $
;;

        MODULE  ?cstartup

        ;; Forward declaration of sections.
        SECTION IRQ_STACK:DATA:NOROOT(3)
        SECTION FIQ_STACK:DATA:NOROOT(3)
        SECTION SVC_STACK:DATA:NOROOT(3)
        SECTION ABT_STACK:DATA:NOROOT(3)
        SECTION UND_STACK:DATA:NOROOT(3)
        SECTION CSTACK:DATA:NOROOT(3)

;
; The module in this file are included in the libraries, and may be
; replaced by any user-defined modules that define the PUBLIC symbol
; __iar_program_start or a user defined start symbol.
;
; To override the cstartup defined in the library, simply add your
; modified version to the workbench project.

        SECTION .intvec:CODE:NOROOT(2)

        PUBLIC  __vector
        PUBLIC  __iar_program_start
        PUBLIC  __vector_0x14
       
        EXTERN    undef_handler, swi_handler, prefetch_handler
        EXTERN    data_handler, irq_handler, fiq_handler
        EXTERN  vPortYieldProcessor
                ARM    ; Always ARM mode after reset   
__vector:
        ldr    pc,[pc,#24]    ; Absolute jump can reach 4 GByte
__undef_handler:
    ldr    pc,[pc,#24]    ; Branch to undef_handler
__swi_handler:
;        ldr    pc,[pc,#24]    ; Branch to swi_handler
        b vPortYieldProcessor
__prefetch_handler:
        ldr    pc,[pc,#24]    ; Branch to prefetch_handler
__data_handler
        ldr    pc,[pc,#24]    ; Branch to data_handler
__vector_0x14
    dc32 0xFFFFFFFF
__irq_handler:
        ldr   pc,[pc, #-0x0120]     ; Branch to irq_handler
__fiq_handler:
        ldr    pc,[pc,#24]    ; Branch to fiq_handler

        ; Constant table entries (for ldr pc) will be placed at 0x20
      dc32    __iar_program_start
      dc32    __undef_handler
      dc32    __swi_handler
      dc32    __prefetch_handler
      dc32    __data_handler
      dc32    0xFFFFFFFF
      dc32    0xFFFFFFFF
      dc32    __fiq_handler

; --------------------
; Mode, correspords to bits 0-5 in CPSR

MODE_MSK DEFINE 0x1F            ; Bit mask for mode bits in CPSR
USR_MODE DEFINE 0x10            ; User mode
FIQ_MODE DEFINE 0x11            ; Fast Interrupt Request mode
IRQ_MODE DEFINE 0x12            ; Interrupt Request mode
SVC_MODE DEFINE 0x13            ; Supervisor mode
ABT_MODE DEFINE 0x17            ; Abort mode
UND_MODE DEFINE 0x1B            ; Undefined Instruction mode
SYS_MODE DEFINE 0x1F            ; System mode

CP_DIS_MASK DEFINE 0xFFFFFFF2

        SECTION .text:CODE:NOROOT(2)

        EXTERN  ?main
        REQUIRE __vector
        EXTERN  low_level_init

        ARM

__iar_program_start:
?cstartup:

I_Bit    DEFINE 0x80            ; when I bit is set, IRQ is disabled
F_Bit    DEFINE 0x40            ; when F bit is set, FIQ is disabled

#define VIC_INT_ENABLE  0xFFFFF014
; Disable all interrupts
                ldr   r0,=VIC_INT_ENABLE
                mov   r1,#0xFFFFFFFF
                str   r1,[r0]

; Execution starts here.
; After a reset, the mode is ARM, Supervisor, interrupts disabled.
; Initialize the stack pointers.
; The pattern below can be used for any of the exception stacks:
; FIQ, IRQ, SVC, ABT, UND, SYS.
; The USR mode uses the same stack as SYS.
; The stack segments must be defined in the linker command file,
; and be declared above.

                mrs         r0,cpsr                             ; Original PSR value
                bic         r0,r0,#MODE_MSK                     ; Clear the mode bits
                orr         r0,r0,#SVC_MODE                     ; Set Supervisor mode bits
                msr         cpsr_c,r0                           ; Change the mode
                ldr         sp,=SFE(SVC_STACK)                  ; End of SVC_STACK

                bic         r0,r0,#MODE_MSK                     ; Clear the mode bits
                orr         r0,r0,#UND_MODE                     ; Set Undefined mode bits
                msr         cpsr_c,r0                           ; Change the mode
                ldr         sp,=SFE(UND_STACK)                  ; End of UND_MODE

                bic         r0,r0,#MODE_MSK                     ; Clear the mode bits
                orr         r0,r0,#ABT_MODE                     ; Set Data abort mode bits
                msr         cpsr_c,r0                           ; Change the mode
                ldr         sp,=SFE(ABT_STACK)                  ; End of ABT_STACK

                bic         r0,r0,#MODE_MSK                     ; Clear the mode bits
                orr         r0,r0,#FIQ_MODE                     ; Set FIR mode bits
                msr         cpsr_c,r0                           ; Change the mode
                ldr         sp,=SFE(FIQ_STACK)                  ; End of FIQ_STACK

                bic         r0,r0,#MODE_MSK                     ; Clear the mode bits
                orr         r0,r0,#IRQ_MODE                     ; Set IRQ mode bits
                msr         cpsr_c,r0                           ; Change the mode
                ldr         sp,=SFE(IRQ_STACK)                  ; End of IRQ_STACK

                bic         r0,r0,#MODE_MSK | I_Bit | F_Bit     ; Clear the mode bits
                orr         r0,r0,#SYS_MODE                     ; Set System mode bits
                msr         cpsr_c,r0                           ; Change the mode
                ldr         sp,=SFE(CSTACK)                     ; End of CSTACK

#ifdef __ARMVFP__
; Enable the VFP coprocessor.
                mov     r0, #BASE_ARD_EIM                   ; Set EN bit in VFP
                fmxr    fpexc, r0                           ; FPEXC, clear others.

; Disable underflow exceptions by setting flush to zero mode.
; For full IEEE 754 underflow compliance this code should be removed
; and the appropriate exception handler installed.
                mov     r0, #0x01000000                          ; Set FZ bit in VFP
                fmxr    fpscr, r0                           ; FPSCR, clear others.
#endif

; Add more initialization here

                BIC     r0, r0, #MODE_MSK      ; Clear the mode bits
                ORR     r0, r0, #SVC_MODE       ; Set SVC mode bits
                MSR     cpsr_c, r0              ; Change the mode

; Continue to ?main for more IAR specific system startup

                ldr     r0,=?main
                bx      r0

                END

deboeck wrote on Monday, April 13, 2009:

Good question. How do I check this in IAR?

Thanks,
Bart

edwards3 wrote on Monday, April 13, 2009:

Open the project options, select the debugger category (from the list on the right side of the options dialogue), see if Use Macro is checked. If it is checked note which file it is used. It will normally have a .mac file extension. Look at the file to see what it does. It probably does something that you need to do manually when you are running without the debugger.

edwards3 wrote on Monday, April 13, 2009:

>Below the cstartup.s file. If I’m not mistaken, the Supervisor mode is set in

Looks ok, provided this is the file being used by both the debug and release builds.

deboeck wrote on Monday, April 13, 2009:

Thanks for explaning!

Use Macro is not checked.

Thanks!
Bart

deboeck wrote on Monday, April 13, 2009:

It is used by the debug and release builds.

Thanks for checking!

deboeck wrote on Monday, April 13, 2009:

for completeness, below portasm.s79

////////////////////////portasm.s79///////////////////////////////

        RSEG ICODE:CODE
        CODE32

    EXTERN vTaskSwitchContext
    EXTERN vTaskIncrementTick
    EXTERN vPortPreemptiveTick
   
    PUBLIC vPortPreemptiveTickEntry
    PUBLIC vPortYieldProcessor
    PUBLIC vPortStartFirstTask

#include "FreeRTOSConfig.h"
#include "ISR_Support.h"

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Starting the first task is just a matter of restoring the context that
; was created by pxPortInitialiseStack().
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
vPortStartFirstTask:
    portRESTORE_CONTEXT

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Manual context switch function.  This is the SWI hander.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
vPortYieldProcessor:
    ADD        LR, LR, #4            ; Add 4 to the LR to make the LR appear exactly
                                ; as if the context was saved during and IRQ
                                ; handler.
                               
    portSAVE_CONTEXT            ; Save the context of the current task…
    LDR R0, =vTaskSwitchContext    ; before selecting the next task to execute.
    mov     lr, pc
    BX R0
    portRESTORE_CONTEXT            ; Restore the context of the selected task.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Preemptive context switch function.  This will only ever get installed if
; portUSE_PREEMPTION is set to 1 in portmacro.h.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
vPortPreemptiveTickEntry:
#if configUSE_PREEMPTION == 1
    portSAVE_CONTEXT            ; Save the context of the current task…
    LDR R0, =vPortPreemptiveTick; before selecting the next task to execute.
    mov     lr, pc
    BX R0
    portRESTORE_CONTEXT            ; Restore the context of the selected task.
#endif

    END

deboeck wrote on Monday, April 13, 2009:

I think I’ve found the issue:

  - the LPC2364 only has 8KB on-chip static RAM. The linker configuration file that I’m using now, explicitely defines the 8KB on-chip static RAM as RAM. Configuring

  #define configTOTAL_HEAP_SIZE        ( ( size_t ) 4000 )

allows to compile, link, and power off/on

  - increasing the 8KB in the linker configuration file to 32KB and configuring

  #define configTOTAL_HEAP_SIZE        ( ( size_t ) 25000 )

allows to link the app and run it in the debugger, power on/off, however, does not work

Please feel free to comment!

Thanks,
Bart