Interrupts working but vTaskDelay crashes?

ktownsend wrote on Tuesday, September 15, 2009:

I’ve been trying to get **FreeRTOS 5.4.2** working with **Crossworks 2.0.3** and an LPC2148.  When I have two simple tasks running incrementing a counter, everything works as expected … the tick counter increments, and the tasks are divided more or less equally.  As soon as I add **vTaskDelay** or anything causing a delay, though, it crashes.  Normally the problem for this is the the tick ISR isn’t working, but in this case it definately does work so I’m not really sure why the delay is causing a problem.

Has anyone had any luck getting FreeRTOS working in Crossworks 2.0? 

If it helps clear anything up, here’s the tick ISR (which seems to work):

        void vTickISR( void ) __attribute__((naked));
    void vTickISR( void )
    /* Save the context of the interrupted task. */
    /* Increment the RTOS tick count, then look for the highest priority
    task that is ready to run. */
    #if configUSE_PREEMPTION == 1
    /* Ready for the next interrupt. */
    /* Restore the context of the new task. */

and the config settings

    #define configUSE_PREEMPTION 1
    #define configUSE_IDLE_HOOK 0
    #define configUSE_TICK_HOOK 0
    #define configCPU_CLOCK_HZ ((unsigned portLONG) 48000000) // =12.0000MHz xtal multiplied by 4 using the PLL.
    #define configTICK_RATE_HZ ((portTickType) 100)
    #define configMAX_PRIORITIES ((unsigned portBASE_TYPE) 4)
    #define configMINIMAL_STACK_SIZE ((unsigned portSHORT) 128)
    #define configTOTAL_HEAP_SIZE ((size_t) (16 * 1024))
    #define configMAX_TASK_NAME_LEN (8)
    #define configUSE_TRACE_FACILITY 1
    #define configUSE_16_BIT_TICKS 0
    #define configIDLE_SHOULD_YIELD 1

and the preprocessor settings in Crossworks:


And last of all the tasks (sorry for the monster post but at least this way everything is clear from the start) … if I remove the delay everything works fine:

    static int task1, task2;
    static portTASK_FUNCTION(vTestTask, pvParameters __attribute__((unused)))
      task1 = 0;
      char *ptr;
      for (;:wink:
        // Task code goes here
        // if (uart1GetChar ((signed portCHAR *) ptr++, 0))
        //   uart1PutChar(*ptr, 0);
    static portTASK_FUNCTION(vUART1Task, pvParameters __attribute__((unused)))
      task2 = 0;
      for (;:wink:
        uart1PutChar(‘1’, 0);
        /* Block for 500ms. */
        const portTickType xDelay = 500 / portTICK_RATE_MS;
    int main(void)
      uart1Init(9600, 80);
      xTaskHandle xTestTaskHandle;
      xTaskCreate (vTestTask, (const signed portCHAR * const)"Test",
                   (tskIDLE_PRIORITY + 2),
      xTaskHandle xUART1TaskHandle;
      xTaskCreate (vUART1Task, (const signed portCHAR * const)"UART1",
                   (tskIDLE_PRIORITY + 2),
      return 0;

sotd wrote on Tuesday, September 15, 2009:

Do you populate SWI handler in vector table to function vPortYieldProcessor?

ktownsend wrote on Tuesday, September 15, 2009:


I’ve got the following:

    /* ISR to handle manual context switches (from a call to taskYIELD()). */
    void vPortYieldProcessor( void ) __attribute__((interrupt("SWI"), naked));

I’m essentially using the standard files from the 2138 port, and I’ve also got everything working Crossworks 2.0 with a 2478 so I’m kind of stumpted on this (since the tick counter is indeed incrementing).

rtel wrote on Tuesday, September 15, 2009:

Is the SWI hander also populated in the vector table, in the start up assembly file?  Something like this:

b     _start /* reset - _start */
ldr   pc, _undf /* undefined - _undf */
ldr   pc, _swi /* SWI - _swi */
ldr   pc, _pabt /* program abort - _pabt */
ldr   pc, _dabt /* data abort - _dabt */
nop /* reserved */
ldr   pc, /* IRQ - read the VIC */
ldr   pc, _fiq /* FIQ - _fiq */

_undf:  .word __undf                    /* undefined */
_swi:   .word vPortYieldProcessor       /* SWI */
_pabt:  .word __pabt                    /* program abort */
_dabt:  .word __dabt                    /* data abort */
_fiq:   .word __fiq                     /* FIQ */


ktownsend wrote on Tuesday, September 15, 2009:


Thanks for the reply.  I’m starting to get reasonably familiar with the lpc2000 family, but ARM assembly is still a big mystery to me even though I’ve made a bit of effort to try to understand some of the basics.  Looking at the Crossworks startup files for the 2100, I can only find the following "Exception Vectors" (in Philips_LPC210x_Startup.s), which I’m guessing isn’t the same?

     * Exception Vectors                                                         *
      ldr pc,   /* reset */
      ldr pc,   /* undefined instruction */
      ldr pc,     /* swi handler */
      ldr pc,  /* abort prefetch */
      ldr pc,  /* abort data */
      .word 0xB9205F88                              /* boot loader checksum */
      ldr pc,                          /* irq handler */
      .word 0xB8A06F60                              /* boot loader checksum */
      ldr pc,     /* irq handler */
      ldr pc,     /* fiq handler */

      .word swi_handler

With the later branching out to "swi_handler" in software code.

In crt0.s I don’t see anything for swi at all … I’ve just got the following:

      mrs r0, cpsr
      bic r0, r0, #0x1F
      /* Setup stacks */
      orr r1, r0, #0x1B /* Undefined mode */
      msr cpsr_cxsf, r1
      ldr sp, =__stack_und_end__
      orr r1, r0, #0x17 /* Abort mode */
      msr cpsr_cxsf, r1
      ldr sp, =__stack_abt_end__
      orr r1, r0, #0x12 /* IRQ mode */
      msr cpsr_cxsf, r1
      ldr sp, =__stack_irq_end__
      orr r1, r0, #0x11 /* FIQ mode */
      msr cpsr_cxsf, r1
      ldr sp, =__stack_fiq_end__
      orr r1, r0, #0x13 /* Supervisor mode */
      msr cpsr_cxsf, r1
      ldr sp, =__stack_svc_end__
      /* Start application in supervisor mode */
      ldr r1, =__stack_end__ /* Setup user/system mode stack */
      mov r2, sp
      stmfd r2!, {r1}
      ldmfd r2, {sp}^
      /* Start application in system mode */
      orr r1, r0, #0x1F /* System mode */
      msr cpsr_cxsf, r1
      ldr sp, =__stack_end__

Should I be adding the _swi line you showed here?  I didn’t need to touch the 2478 startup files to get FreeRTOS working, but the 23xx and 24xx don’t use the same startup files or interrupt handler as the 2100 either.

ktownsend wrote on Tuesday, September 15, 2009:

Digging around JC Wren’s demo code (which I’m using at the basis of much of my own code) I came across this, but I’m not sure where to insert it in the context of Crossworks being utterly useless with (amongst other things, sigh) assembly and the startup files.

    @  FreeRTOS uses SWI to yield process, but it’s greedy and wants SWI all to its
    @  self.  So… Special handling it is!
            ldmfd   sp!, {r4, lr}           @ Recover r4, lr
            b       vPortYieldProcessor     @ Yield… yield like the wind!

ktownsend wrote on Tuesday, September 15, 2009:

I think I’ve got it … the Crossworks vector table maps _swi to swi_handler, and adding this to the FreeRTOSConfig file gets everything (seemingly) working properly without having to modify the Crossworks files:

    #define vPortYieldProcessor swi_handler

Thanks to both of you for pointing me in the right direction.