This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

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.

Parents
  • 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?

Reply
  • 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?

Children
  • 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

  • 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