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.
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.
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
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