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.
The following comment is on a website for the pC/OS RTOS kernel (http://www.embedded-os.de/) The port of the pC/OS Kernel on AT91SAM7Sxx is now finished. As Toolchain the IAR Embedded Workbench was used. Sorry to Keil, with "...?T" and "...?A" it's not really possible to create a good port for ARM and Thumb mode. If anyone knows what this means, will you please explain it? Thanks.
We do not understand this comment either. Reinhard
My problem was the assembler file. This file uses variables and functions defined in C and the assembler functions are called from C. I have'nt found any way to create a assembler file, that works in thumb- and arm-mode without adding ..?T (for thumb mode) or ..?A (for arm mode). Does anyone have any idea for this problem ?
Frank, If you want to have a function in an assembly language source file that can be used also from C and that function may be called from either arm- or thumb-mode then you have to provide an arm and a thumb entry as shown in the example below. The compiler does this automatically for C functions on demand. But for assembly labguage files, this need to be done manually. Peter
AREA MYFUNC, CODE, READONLY, ALIGN=2 ; MYFUNC can be called from arm and thumb mode PUBLIC MYFUNC?T, MYFUNC?A MYFUNC?T PROC CODE16 ; thumb interworking entry BX PC ; branch to 'MYFUNC?A' NOP ENDP MYFUNC?A PROC CODE32 ; arm entry ! ; ... BX LR ENDP END
Thanks Peter, this fixes the problem for calling ASM from C. Do you have a same simple solution for calling C from ASM ? And do this really work (see BX PC and BX LR inside a context-switch):
AREA PCOS, CODE, READONLY, ALIGN=2 PUBLIC OSIntCtxSw?T , OSIntCtxSw?A OSIntCtxSw?T PROC CODE16 ; thumb interworking entry BX PC ; branch to 'OSIntCtxSw?A' NOP ENDP OSIntCtxSw?A PROC CODE32 ; arm entry ! LDR R6, =OSTCBHighRdy ; get TCB of highest priority task LDR R4, =OSTCBCur ; save as current LDR R6, [R6] STR R6, [R4] LDR SP, [R6] ; restore new stack-ptr LDMFD SP!, {R4} ; pop new task CPSR MSR SPSR_cxsf, R4 LDMFD SP!, {R0-R12,LR,PC}^ ; pop new task context BX LR ENDP END
The 'BX LR' seems to be incorrect in this context where the PC is restored by using load multiple. The code I've posted was meant for the simple call/return case, not for task-switching. Calling C functions from asm: this requires 'EXTERN' directives in the asm file as shown in the example below. Calling the external C-function from within Thumb-code requires 'CFUNC?T' to be called, and 'CFUNC?A' otherwise (the names I've used in the example). Hope that helps you, Peter
EXTERN CODE32 (CFUNC?A) EXTERN CODE16 (CFUNC?T) AREA PCOS, CODE, READONLY, ALIGN=2 PUBLIC OSIntCtxSw?T , OSIntCtxSw?A OSIntCtxSw?T PROC CODE16 ; thumb interworking entry BX PC ; branch to 'OSIntCtxSw?A' NOP ENDP OSIntCtxSw?A PROC CODE32 ; arm entry ! ;; LDR R6, =OSTCBHighRdy ; get TCB of highest priority task ;; LDR R4, =OSTCBCur ; save as current ;---------------------------- BL CFUNC?A ; within ARM --> ?A ; BL CFUNC?T ; within Thumb --> ?T ;---------------------------- LDR R6, [R6] STR R6, [R4] LDR SP, [R6] ; restore new stack-ptr LDMFD SP!, {R4} ; pop new task CPSR MSR SPSR_cxsf, R4 LDMFD SP!, {R0-R12,LR,PC}^ ; pop new task context ;;BX LR ENDP END
Do you have a same simple solution for calling C from ASM ? While this is possible, it is dangerous or, at best, require a large overhead. There is no "rule" whatsoever as to which registers etc a C routine will affect without restoring. This can, of course be found out, but as no "rule" exist, it may be different in the next release of the compiler. I have in ONE case called C from assembler, and, in order to be safe I saved everything before the call and restored it afterwards. This is so combersome/time consuming that in the few other cases I have considered calling C from assembler, I did not, Erik
I have updated the pC/OS RTOS kernel (http://www.embedded-os.de/) and included the port using Keil. But I can't get it stable ??? - using the IAR-Toolchain I have no problems...
I need help.... The following code fragment is the start of Task1() without the two memory-manager calls (commented). If I step over/in " b 0x001010d8" the processor jumps to the DAbt_Handler at address 0x00000010. Whats wrong with this part ???
B530 push {r4-r5,lr} 2400 mov r4,#0x00 F000 bl AppTickInit(0x00101290) - Part #1 F8DE bl AppTickInit(0x00101290) - Part #2 E000 b 0x001010d8 - *** -> DAbt_Handler(0x00000010) 3401 add r4,#0x01 | <- 1C20 add r0,r4,#0 <- | 4911 ldr r1,[pc,#0x0044] | 4288 cmp r0,r1 | D3FA bcc 0x001010d6 ---- ...
Frank, Your code snipped shows -
... F000 bl AppTickInit(0x00101290) - Part #1 F8DE bl AppTickInit(0x00101290) - Part #2 ...
//--- Thumb-mode: ... 01000CCE 3001 ADD R0,#0x1 01000CD0 3102 ADD R1,#0x2 01000CD2 F7FF BL AppTickInit?T ; T=0x1000C71 (1) 01000CD4 FFCD BL AppTickInit?T ; T=0x1000C71 (2) ... //--- Thumb to Arm Interwork-Stub: 01000C70 AppTickInit?T PROC THUMB 01000C70 4778 BX R15 01000C72 46C0 NOP ; MOV R8,R8 01000C74 ENDP //--- Arm Function: 01000C74 AppTickInit?A: ; FUNCTION START 257: int ArmF (int n1, int n2) __arm { 01000C74 E1A03001 MOV R3,R1 ; n2 01000C78 ---- Variable 'n2' assigned to Register 'R3' ---- 01000C78 E1A02000 MOV R2,R0 ; n1 01000C7C ---- Variable 'n1' assigned to Register 'R2' ---- 258: return (n1 * n2 + n1 * n2); 01000C7C E1A01003 MOV R1,R3 ; n2 01000C80 E1A00002 MOV R0,R2 ; n1 01000C84 E0000091 MUL R0,R1,R0 ; n2 01000C88 E0800000 ADD R0,R0,R0 259: } 01000C8C E12FFF1E BX R14 01000C90 ; END 'AppTickInit?A'
thanks, but see the main.c - AppTickInit() is a C-function called from main(). I think, this is to handle by the compiler... Have the Keil-compiler optimizing problems with not direct called functions (see Task1..3) or problems with C-Thumb-code mixed with ASM-Thumb/ARM-code ? Frank
... Sorry ! see the main.c - AppTickInit() is a C-function called from C-function Task1(). But the problem is still the same...
... more tests using the simulator and the board... Following test was running on the board: * If I set a breakpoint at
bl AppTickInit(0x00101290) - Part #1
push {r4-r5,lr}
B530 push {r4-r5,lr} 2500 mov r5,#0x00 2400 mov r4,#0x00
The CARM compiler handles all the interworking automatically. As usual with software, there is always the chance to get into some 'notch'. You should provide a boiled down example since the code fragments simply don't give enough details. Your most recent post looks like a stack overrun/underrun problem. Peter
You can download the hole code of the pC/OS RTOS kernel from http://www.embedded-os.de/index.html?pcos.htm