tns1 wrote on Wednesday, 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
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