Porting FreeRtos to LPC2478 under Keil

I see some have already tried this, so I wonder if you could look at my list of changes and see if they make sense. Right now, the first tasks gets launched, but as soon as I call taskSuspend it then it hangs up in the idle task and subsequent tasks to not get launched. thanks Create uVision project for LPC2478 (which uses LPC2400.s) Start with FreeRtos v5.1.1 demo ARM7_LPC2129_Keil_RVDS use Keil’s lpc23xx.h instead of lpc21xx.h add LPC2400.s to project, edit to add : IMPORT    vPortYieldProcessor    SWI_Addr        DCD     vPortYieldProcessor    also comment out user mode init and force svr mode before jump to C add NO_EMC_SETUP to asm options – just want simplest simulation of code in flash memory edit portable.h to create new device ARM7_LPC2478_KEIL_RVDS  create folder RVDS/ARM7_LPC2478 for new device by copying folder RVDS/ARM7_LPC21xx add new device symbol and paths to uvision project options edit portASM.s to match datasheet and use of T0MR1 ;;VICVECTADDR    EQU    0xFFFFF030 VICVECTADDR    EQU    0xFFFFFF00 T0IR        EQU    0xE0004000 ;;T0MATCHBIT    EQU    0x00000001 T0MATCHBIT    EQU    0x00000002 edit port.c prvSetupTimerInterrupt() by examining GCC demo for 23xx : change T0MR0 to T0MR1 change VICVectAddr0 to VICVectAddr4 change VICVectCntl0 to VICVectCntl4

Porting FreeRtos to LPC2478 under Keil

Also in port.c : change     VICVectCntl4 = 1;//priority 1 (0 is highest) I must not have gotten all the changes necessary. Under the simulator, once the processor gets into IRQ mode by the first timer tick, it never comes out. I have the timer working, and interrupts are happening at the proper interval. Using keils peripheral view, I can see the timer interrupt being set and cleared as expected, but I do not see the interrupt being acknowledged in the vic vicaddress register even though it is being written to by the code. I am not sure it would actually be cleared though. I also wonder about the stack setup in LPC2400.s. The user SP is never set since once you enter user mode, you can’t easily hop back to svr mode. How to set the user SP and also start in svr mode?

Porting FreeRtos to LPC2478 under Keil

How have you installed the IRQ handler? Does it vector directly to the peripheral, or does it vector to a common interrupt entry function? The IRQ should be installed something like this, although this might not be quite right: ldr   pc, [pc,#-0xFF0]                /* IRQ – read the VIC        */ so the whole vector table looks 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, [pc,#-0xFF0]                /* 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                        */ __undf: b     .                         /* undefined                */ __pabt: b     .                         /* program abort            */ __dabt: b     .                         /* data abort                */ __fiq:  b     .                         /* FIQ                        */

Porting FreeRtos to LPC2478 under Keil

Here is all the modified code, changes marked with ***. Your piece looks like it is for a 21xx under GCC, so similar steps but different syntax. The Vic Vector register is different for 24xx parts. BTW, why is a read from VicAddress (xFFFFFF00) coded like LDR PC, [PC, #-0x0120] ? PC is 0x18, so this appears to evaluate to PC <- [PC+(#immed)+8]. Somewhere I saw the extra 8byte offset documented, but I can’t find it now. ***LPC2400.s startup & vector table mods         IMPORT    vPortYieldProcessor    ;***    Vectors         LDR     PC, Reset_Addr                         LDR     PC, Undef_Addr                 LDR     PC, SWI_Addr                 LDR     PC, PAbt_Addr                 LDR     PC, DAbt_Addr                 NOP                            ; Reserved Vector ;               LDR     PC, IRQ_Addr                 LDR     PC, [PC, #-0x0120]     ; Vector from VicVectAddr (xFFFFFF00)                 LDR     PC, FIQ_Addr Reset_Addr      DCD     Reset_Handler Undef_Addr      DCD     Undef_Handler SWI_Addr        DCD     vPortYieldProcessor    ;***     PAbt_Addr       DCD     PAbt_Handler DAbt_Addr       DCD     DAbt_Handler                 DCD     0                      ; Reserved Address IRQ_Addr        DCD     IRQ_Handler FIQ_Addr        DCD     FIQ_Handler Undef_Handler   B       Undef_Handler SWI_Handler     B       SWI_Handler PAbt_Handler    B       PAbt_Handler DAbt_Handler    B       DAbt_Handler IRQ_Handler     B       IRQ_Handler FIQ_Handler     B       FIQ_Handler … ; 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 ;  Enter User Mode and set its Stack Pointer – skip this *** ;                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 ***port.c mods #define portTIMER_MATCH_ISR_BIT        ( ( unsigned portCHAR ) 0x02 ) static void prvSetupTimerInterrupt( void ) { unsigned portLONG ulCompareMatch;     PCLKSEL0 = (PCLKSEL0 & (~(0x3<<2))) | (0x01 << 2); //***setup for CCLK     T0TCR  = 2;         /* Stop and reset the timer */ //***     T0CTCR = 0;         /* Timer mode               */ //***     /* A 1ms tick does not require the use of the timer prescale.  This is     defaulted to zero but can be used if necessary. */     T0PR = portPRESCALE_VALUE;     /* Calculate the match value required for our wanted tick rate (1ms). */     ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;     /* Protect against divide by zero.  Using an if() statement still results     in a warning – hence the #if. */     #if portPRESCALE_VALUE != 0     {         ulCompareMatch /= ( portPRESCALE_VALUE + 1 );     }     #endif     T0MR1 = ulCompareMatch; //*** timer match value     /* Generate tick with timer 0 compare match on register 1. */     T0MCR = ((portRESET_COUNT_ON_MATCH | portINTERRUPT_ON_MATCH) << 3);//***     /* Clear and Setup the VIC for the timer 0, IRQ (not FIQ). */     VICIntSelect &= ~( portTIMER_VIC_CHANNEL_BIT );     VICIntEnable |= portTIMER_VIC_CHANNEL_BIT;         /* The ISR installed depends on whether the preemptive or cooperative     scheduler is being used. */     #if configUSE_PREEMPTION == 1     {            VICVectAddr4 = ( unsigned portLONG ) vPreemptiveTick; //*** interrupt 4 is timer0     }     #else     {         VICVectAddr4 = ( unsigned portLONG ) vNonPreemptiveTick;//***     }     #endif     VICVectCntl4 = 1;//*** priority 1 (0 is highest)     /* Start the timer – interrupts are disabled when this function is called     so it is okay to do this here. */     T0TCR = portENABLE_TIMER; } *** portASM.s mods ;VICVECTADDR    EQU    0xFFFFF030 VICVECTADDR    EQU    0xFFFFFF00    ;*** T0IR        EQU    0xE0004000 ;T0MATCHBIT    EQU    0x00000001 T0MATCHBIT    EQU    0x00000002    ;*** vPreemptiveTick     PRESERVE8     portSAVE_CONTEXT                ; Save the context of the current task.        LDR R0, =vTaskIncrementTick            ; Increment the tick count.      MOV LR, PC                    ; This may make a delayed task ready     BX R0                        ; to run.         LDR R0, =vTaskSwitchContext            ; Find the highest priority task that     MOV LR, PC                    ; is ready to run.     BX R0         MOV R0, #T0MATCHBIT                ; Clear the timer event     LDR R1, =T0IR     STR R0, [R1]     LDR    R0, =VICVECTADDR            ; Acknowledge the interrupt        STR    R0,[R0]     portRESTORE_CONTEXT                ; Restore the context of the highest                             ; priority task that is ready to run.     END

Porting FreeRtos to LPC2478 under Keil

*** more mods in LPC2400.s change PLLCFG_Val      EQU     0x0000000E ;for 60mhz with a 12Mhz osc change CCLKCFG_Val     EQU     0x00000005 *** mods in serial.c change ulDivisor = configCPU_CLOCK_HZ / ulWantedClock /4;//div by 4 for pclk change VICVectAddr7 = ( unsigned portLONG ) vUART_ISREntry;//vector 7 change VICVectCntl7 = serU1VIC_CHANNEL | serU1VIC_ENABLE; After these last changes, my project runs correctly in both the Keil simulator and on the EA board (some pin select changes required)

Porting FreeRtos to LPC2478 under Keil

Thank you for taking the time to report this back. It will be helpful to the rest of the community.