We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
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.
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?
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