|
|
FreeRTOS Support Archive
The FreeRTOS support forum is used to obtain active support directly from Real
Time Engineers Ltd. In return for using our top quality software and services for
free, we request you play fair and do your bit to help others too! Sign up
to receive notifications of new support topics then help where you can.
This is a read only archive of threads posted to the FreeRTOS support forum.
The archive is updated every week, so will not always contain the very latest posts.
Use these archive pages to search previous posts. Use the Live FreeRTOS Forum
link to reply to a post, or start a new support thread.
[FreeRTOS Home] [Live FreeRTOS Forum] [FAQ] [Archive Top] [January 2009 Threads] Porting FreeRtos to LPC2478 under KeilPosted by tns1 on January 27, 2009 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 : IMPORTvPortYieldProcessor 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 ;;VICVECTADDREQU0xFFFFF030 VICVECTADDREQU0xFFFFFF00 T0IREQU0xE0004000 ;;T0MATCHBITEQU0x00000001 T0MATCHBITEQU0x00000002
edit port.c prvSetupTimerInterrupt() by examining GCC demo for 23xx : change T0MR0 to T0MR1 change VICVectAddr0 to VICVectAddr4 change VICVectCntl0 to VICVectCntl4
RE: Porting FreeRtos to LPC2478 under KeilPosted by tns1 on January 28, 2009 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?
RE: Porting FreeRtos to LPC2478 under KeilPosted by Dave on January 28, 2009 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*/
RE: Porting FreeRtos to LPC2478 under KeilPosted by tns1 on January 28, 2009 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
IMPORTvPortYieldProcessor;*** 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
;VICVECTADDREQU0xFFFFF030 VICVECTADDREQU0xFFFFFF00;*** T0IREQU0xE0004000 ;T0MATCHBITEQU0x00000001 T0MATCHBITEQU0x00000002;***
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]
LDRR0, =VICVECTADDR; Acknowledge the interrupt STRR0,[R0]
portRESTORE_CONTEXT; Restore the context of the highest ; priority task that is ready to run. END
RE: Porting FreeRtos to LPC2478 under KeilPosted by tns1 on January 30, 2009 *** 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)
RE: Porting FreeRtos to LPC2478 under KeilPosted by MEdwards on January 30, 2009 Thank you for taking the time to report this back. It will be helpful to the rest of the community.
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.
|