Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem


Loading

Porting FreeRtos to LPC2478 under Keil

Posted 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 Keil

Posted 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 Keil

Posted 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 Keil

Posted 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 Keil

Posted 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 Keil

Posted 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.


[ Back to the top ]    [ About FreeRTOS ]    [ Privacy ]    [ Sitemap ]    [ ]


Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

NXP tweet showing LPC5500 (ARMv8-M Cortex-M33) running FreeRTOS.

Meet Richard Barry and learn about running FreeRTOS on RISC-V at FOSDEM 2019

Version 10.1.1 of the FreeRTOS kernel is available for immediate download. MIT licensed.

View a recording of the "OTA Update Security and Reliability" webinar, presented by TI and AWS.


Careers

FreeRTOS and other embedded software careers at AWS.



FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Espressif ESP32

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Renesas

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS

Xilinx Microblaze and Zynq partner