Keil Logo Arm Logo

Discussion Forum

ARM: Porting an application from IAR to Keil (Porteil QK QP)

Next Thread | Thread List | Previous Thread Start a Thread | Settings

Details Message
Read-Only
Author
Rinie Romain
Posted
25-Nov-2011 08:29 GMT
Toolset
ARM
New! ARM: Porting an application from IAR to Keil (Porteil QK QP)

Hello all,

I've just port the QK Os and the QP framework (state machine framework) from the LM3S6965 to the LM3S9B96.

I've done this using IAR and now I'm trying to use Keil as my company own some licenses for Keil.

I have a problem with an IAR specific directive. It's concerning the vector table, to make it ends up at physical address 0x0000.0000 they use this method in IAR:

__root const uVectorEntry __vector_table[] @ ".intvec" =
{
    { .ulPtr = (unsigned long)pulStack + sizeof(pulStack) },
                                            // The initial stack pointer
    __iar_program_start,                    // The reset handler
....
    Ethernet_IRQHandler,                    // Ethernet
    Hibernate_IRQHandler                    // Hibernate
};

How to convert the @ ".intvec" or what the equivalent of this part of code in Keil?

Maybe some information here but for Cx51 compiler...:
http://www.keil.com/support/man/docs/c51/c51_intvector.htm

I also have some issues finding an equivalent to ".noinit" in this part of code: (used to reserve space for the system stack)

static unsigned long pulStack[STACK_SIZE/sizeof(unsigned long)] @ ".noinit";

Thanks in advance for any help or suggestion about this two issues.

Read-Only
Author
Per Westermark
Posted
25-Nov-2011 08:47 GMT
Toolset
ARM
New! RE: ARM: Porting an application from IAR to Keil (Porteil QK QP)

Have you looked at all the Keil examples?

They place the interrupt vector table at the start, which they basically have to.

There are a number of threads on this forum discussing zero-init variables.

But in this case you don't need any zero-init stack unless you are very pressed for startup time. It's better to have the stack zero-initialized just to make sure that all runs of the program have the same data on the stack - easier to get same malfunction on multiple runs if you have some uninitialized auto variables.

Read-Only
Author
Rinie Romain
Posted
28-Nov-2011 09:41 GMT
Toolset
ARM
New! RE: ARM: Porting an application from IAR to Keil (Porteil QK QP)

Thanks westermark for your reply, thanks to your advice I finally got it working!

Now I'm blocked on some library generation! I want to create the library used by QP for Keil.
I get a cpu and fpu attributes not compatible error.

I use armcc like this:

armcc -J \IncludeFolder -O3 -g --cpu cortex-m3 --debug -c SourceFolder\source.c -o Output\lib.obj

And then armar to create the library:
armar -r Library\Library1.lib Output\lib.obj

When Keil try to link my program I get this two error:

QP.axf: Error: L6366E: qmp_get.obj attributes are not compatible with the provided cpu and fpu attributes .
QP.axf: Error: L6242E: Cannot link object qmp_get.obj as its attributes are incompatible with the image attributes.

Do someone have an idea about this issue? I check cpu should be cortex-m3 and fpu the value by default. If I choose fpu=none I got some error because of some float type variable used in my program.

Thanks in advance for any advise and help

Read-Only
Author
Rinie Romain
Posted
30-Nov-2011 00:45 GMT
Toolset
ARM
New! RE: ARM: Porting an application from IAR to Keil (Porteil QK QP)

I've sold the previous issue but now I have some problem with an assembler file...

I have one version for GNU and another one for IAR but for both I don't understand how it is working...

I got some error like Unknown opcode CODE:CODE:ROOT or unknown opcode PUBLIC, I know I should translate the asm file for KEIL but it's hard to find information about what my code should do!

Here is the first part of the file for IAR:

    RSEG CODE:CODE:NOROOT(2)

    PUBLIC  PendSV_Handler    ; CMSIS-compliant PendSV exception name
    PUBLIC  QK_init
    PUBLIC  SVC_Handler       ; CMSIS-compliant SVC exception name

    EXTERN  QK_schedPrio_     ; external reference
    EXTERN  QK_sched_         ; external reference

And this should be the same, but for GNU:

    .syntax unified
    .thumb
    .section .text.QK_init
    .global QK_init
    .type   QK_init, %function

Then the code should set some priorities and disable and restore interrupt, this part should not be a problem.
My problem is about the code attached above, QK_init is called from the C program, how to declare it for Keil armasm?

Read-Only
Author
Rinie Romain
Posted
1-Dec-2011 01:19 GMT
Toolset
ARM
New! RE: ARM: Porting an application from IAR to Keil (Porteil QK QP)

Finally I change the ASM code as I can, now it's linking but I don't have interrupt on my board...

Here is the first line of the ASM code:

        GLOBAL  PendSV_Handler    ; CMSIS-compliant PendSV exception name GLOBAL=EXPORT
    GLOBAL  QK_init
    GLOBAL  SVC_Handler       ; CMSIS-compliant SVC exception name

    IMPORT  QK_schedPrio_     ; external reference
    IMPORT  QK_sched_         ; external reference


        AREA |.text.QK_init|, CODE, READONLY, ALIGN=2
        THUMB
        REQUIRE8
        PRESERVE8

For the AREA statement should I keep |text.Qk_init| or simply |text| ?

This is the code folowing:

QK_init
    MRS     r0,PRIMASK        ; store the state of the PRIMASK in r0
    CPSID   i                 ; disable interrupts (set PRIMASK)

    LDR     r1,=0xE000ED18    ; System Handler Priority Register
    LDR     r2,[r1,#8]        ; load the System 12-15 Priority Register
    MOVS    r3,#0xFF
    LSLS    r3,r3,#16
    ORRS    r2,r3             ; set PRI_14 (PendSV) to 0xFF
    STR     r2,[r1,#8]        ; write the System 12-15 Priority Register
    LDR     r2,[r1,#4]        ; load the System 8-11 Priority Register
    LSLS    r3,r3,#8
    BICS    r2,r3             ; set PRI_11 (SVCall) to 0x00
    STR     r2,[r1,#4]        ; write the System 8-11 Priority Register

    MSR     PRIMASK,r0        ; restore the original PRIMASK
    BX      lr                ; return to the caller

PendSV_Handler
    CPSID   i                 ; disable interrupts at processor level
    BL      QK_schedPrio_     ; check if we have preemption
    CMP     r0,#0             ; is prio == 0 ?
    BNE.N   scheduler         ; if prio == 0, branch to scheduler

...

I someone can help me with that because it's really hard for me to find any course about the assembler file for armasm... Tanks

Read-Only
Author
Rinie Romain
Posted
1-Dec-2011 09:40 GMT
Toolset
ARM
New! RE: ARM: Porting an application from IAR to Keil (Porteil QK QP)

In case someone need it one day, here is the qk_port.s now working to make QP library in Keil for the LM3S9B96 board (should be the same for any Cortex M3):

        AREA CODE,CODE
        THUMB
        REQUIRE8
        PRESERVE8
        ;ENTRY

    GLOBAL  QK_init
        GLOBAL  PendSV_Handler    ; CMSIS-compliant PendSV exception name GLOBAL=EXPORT
    GLOBAL  SVC_Handler       ; CMSIS-compliant SVC exception name

    IMPORT  QK_schedPrio_     ; external reference
    IMPORT  QK_sched_         ; external reference


;*****************************************************************************
;
; The QK_init function sets the priorities of PendSV and SVCall exceptions
; to 0xFF and 0x00, respectively. The function internally disables
; interrupts, but restores the original interrupt lock before exit.
;
;*****************************************************************************
QK_init
    MRS     r0,PRIMASK        ; store the state of the PRIMASK in r0
    CPSID   i                 ; disable interrupts (set PRIMASK)

    LDR     r1,=&E000ED18     ; System Handler Priority Register
    LDR     r2,[r1,#8]        ; load the System 12-15 Priority Register
    MOVS    r3,#0xFF
    LSLS    r3,r3,#16
    ORRS    r2,r3             ; set PRI_14 (PendSV) to 0xFF
    STR     r2,[r1,#8]        ; write the System 12-15 Priority Register
    LDR     r2,[r1,#4]        ; load the System 8-11 Priority Register
    LSLS    r3,r3,#8
    BICS    r2,r3             ; set PRI_11 (SVCall) to 0x00
    STR     r2,[r1,#4]        ; write the System 8-11 Priority Register

    MSR     PRIMASK,r0        ; restore the original PRIMASK
    BX      lr                ; return to the caller


;*****************************************************************************
;
; The PendSV_Handler exception hanlder is used for handling asynchronous
; preemptions in QK. The use of the PendSV exception is the recommended
; and most efficient method for performing context switches with ARM Cortex.
;
; The PendSV exception should have the lowest priority in the whole system
; (0xFF, see QK_init). All other exeptions and interrupts should have higher
; priority. For example, for NVIC with 2 priority bits all interrupts and
; exceptions must have numerical value of priority lower than 0xC0. In this
; case the interrupt priority levels available to your applications are (in
; the order from the lowest urgency to the highest urgency): 0x80, 0x40, 0x00.
;
; Also, *all* ISRs in the QK application must trigger the PendSV exception
; by calling the QK_ISR_EXIT() macro.
;
; Due to tail-chaining and its lowest priority, the PendSV exception will be
; entered immediately after the exit from the *last* nested interrupt (or
; exception). In QK, this is exactly the time when the QK scheduler needs to
; check for the asynchronous preemptions.
;
;*****************************************************************************
PendSV_Handler
    CPSID   i                 ; disable interrupts at processor level
    BL      QK_schedPrio_     ; check if we have preemption
    CMP     r0,#0             ; is prio == 0 ?
    BNE.N   scheduler         ; if prio == 0, branch to scheduler

    CPSIE   i                 ; enable interrupts at processor level
    MOVS    r0,#0x6
    MVNS    r0,r0             ; r0:=~0x6=0xFFFFFFF9
    BX      r0                ; exception-return to the task

scheduler
    MOVS    r3,#1
    LSLS    r3,r3,#24         ; r3:=(1 << 24), set the T bit  (new xpsr)
    LDR     r2,=QK_sched_     ; address of the QK scheduler   (new pc)
    LDR     r1,=svc_ret       ; return address after the call (new lr)
    PUSH    {r1-r3}           ; push xpsr,pc,lr
    SUB     sp,sp,#(4*4)      ; don't care for r12,r3,r2,r1
    PUSH    {r0}              ; push the prio argument        (new r0)
    MOVS    r0,#0x6
    MVNS    r0,r0             ; r0:=~0x6=0xFFFFFFF9
    BX      r0                ; exception-return to the scheduler

svc_ret
    CPSIE   i                 ; enable interrupts to allow SVCall exception
    SVC     0                 ; SV exception returns to the preempted task



;*****************************************************************************
;
; The SVC_Handler exception handler is used for returning back to the
; interrupted context (task or interrupt). The SVC exception should have
; the lowest priority in the whole system (see QK_init). The SVCall
; exception simply removes its own interrupt stack frame from the stack and
; returns to the preempted task using the interrupt stack frame that must be
; at the top of the stack.
;
;*****************************************************************************
SVC_Handler
    ADD     sp,sp,#(8*4)      ; remove one interrupt frame from the stack
    BX      lr                ; return to the preempted task
        ALIGN 2,0,0xFF                                    ; make sure the END is properly aligned
    END

Now my QP is working on the LM3S9B96 with Keil uVision 4

Next Thread | Thread List | Previous Thread Start a Thread | Settings

arm-logo-small

Keil logo
Important information

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies.