A LPC23xx/24xx port for KEIL uVision?

tjohansen wrote on Thursday, March 05, 2009:

Hallo

Is there any available port for the LPC24xx line of MCU’s using Keil uVision.
There is one using the LPC2129 in the Demo folder. I know I could use this one as a base, but it would save me some hours of work i one allready was available :slight_smile:

/Thomas

rtel wrote on Thursday, March 05, 2009:

Hi - I posted some steps to take to convert from the 2129 to the 2368 in the LPC2000 forum for you (in response to your post).   Hope that helps.

Regards.

tjohansen wrote on Friday, March 06, 2009:

thanks a lot…   I have read the post…

I do have a problem. I have used the 2129 Keil demo as a base. I have adjusted the timer setup, the startup.s and the pll.

But I do have a crash when I start the scheduler. The debugger disconnects.
I disconnect happens in the portRESTORE_CONTEXT macro and it happen at the last asm line:

From portASM.s

vPortStartFirstTask
    PRESERVE8
    portRESTORE_CONTEXT

From portmacro.inc:
    MACRO
    portRESTORE_CONTEXT

    LDR   R0, =pxCurrentTCB
    LDR   R0, [R0]       
    LDR   LR, [R0]
    LDR   R0, =ulCriticalNesting
    LDMFD LR!, {R1}   
    STR   R1, [R0]               
    LDMFD LR!, {R0}
    MSR   SPSR_cxsf, R0           
    LDMFD LR, {R0-R14}^
    NOP
    LDR   LR, [LR, #+60]
    SUBS  PC, LR, #4  <— crash happens here…???
         MEND

My disassambly looks like this:

    78:         portRESTORE_CONTEXT
    79: 
    80: vPortYield
    81: 
    82:         PRESERVE8
    83: 
0x00001C94  E59F0164  LDR       R0,[PC,#0x0164]
0x00001C98  E5900000  LDR       R0,[R0]
0x00001C9C  E590E000  LDR       R14,[R0]
0x00001CA0  E59F015C  LDR       R0,[PC,#0x015C]
0x00001CA4  E8BE0002  LDMIA     R14!,{R1}
0x00001CA8  E5801000  STR       R1,[R0]
0x00001CAC  E8BE0001  LDMIA     R14!,{R0}
0x00001CB0  E16FF000  MSR       SPSR_cxsf,R0
0x00001CB4  E8DE7FFF  LDMIA     R14,{R0-R14}^
0x00001CB8  E1A00000  NOP      
0x00001CBC  E59EE03C  LDR       R14,[R14,#0x003C]
0x00001CC0  E25EF004  SUBS      PC,R14,#0x00000004 <— Stops here…
    84:         SVC 0
0x00001CC4  EF000000  SWI       0x00000000
    85:         bx lr

Any idea what could be wrong?? Has it something todo with the timer interrupt?? or maybe the PRESERVE directive used before the call to portRESTORE_CONTEXT?

/Thomas

edwards3 wrote on Friday, March 06, 2009:

Most likely the cpu is in the wrong mode. The cpu must be in Supervisor mode when that instruction is executed. Normally if using FreeRTOS a switch to Supervisor mode is made before main() is called.

tjohansen wrote on Monday, March 09, 2009:

I have switch to supervisor mode in my startup file. But in supervisor mode, the timer0 interrupt doesnt fire.
The vPreemptiveTick function is only called if the processor is in user mode???

Exception vectors:
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, #-0x0FF0]     ; Vector from VicVectAddr
                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

Last part of statrup:

; 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
;               MSR     CPSR_c, #Mode_USR
;               IF      :DEF:__MICROLIB
  ;              EXPORT __initial_sp
   ;             ELSE
   ;             MOV     SP, R0
   ;             SUB     SL, SP, #USR_Stack_Size
    ;            ENDIF

davedoors wrote on Monday, March 09, 2009:

Looks fine. Don’t know why it would not work.

tjohansen wrote on Monday, March 09, 2009:

An update:

The vPreemptiveTick is called. But just once. Some how is the timer0 interrupt not working anymore when fired once.
I have debuged the sam code that resets the timer0 at it seems to be ok. It works great in the simulator in Keil uVision, but not on the real target.

If I try another project that uses the timer0 it works ok…

Could be something with the fact, that I actual uses som LPC21xx asm code and not from the lpc24xx GCC demo??

If I look at the the LPC23xx GCC demo’s, the vPreemtiveTick is written as a C function. But in functionality it does the same as the assembler written vPreemtiveTick in the lpc21xx demo?? —

edwards3 wrote on Monday, March 09, 2009:

You have to clear the interrupt in both the timer peripheral and in the VIC. Are you clearing it in the VIC?

    /* Clear the ISR in the VIC. */
    VICVectAddr = serCLEAR_VIC_INTERRUPT;

The value actually written does not matter.

tjohansen wrote on Tuesday, March 10, 2009:

Yes I do:

vPreemptiveTick

   PRESERVE8

   portSAVE_CONTEXT

   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.

tjohansen wrote on Tuesday, March 10, 2009:

Hi

I have now wolved the issue. I have missed changing the address of the VICVECTADDR. It was defined to 0xFFFFFF30, but the correct address is 0xFFFFFF00 in the LPC2478…

/Thomas