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

...?T and ...?A

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.

  • Sounds like a complaint about the segment naming convention? Not that I see how that would necessarily be a problem for writing an OS. Perhaps the granularity of the segments and ARM/Thumb mode isn't high enough, or they want mixed-mode segments, or something like that.

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

    The opcodes indicate that the code is runing in thumb mode. But the target of the 'BL' shows 0x00101290, this is Arm-mode (even address, thumb mode would be 0x00101291).
    In this case, you need an interwork-stub, that is code that changes from thumb- to arm-mode.

    Here is an example of how that looks like:

    //--- 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'
    

    Peter

  • 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
    register r4 is not zero in the register-window???
    * if I set a breakpoint at
    push    {r4-r5,lr}
    and step forward, the register r4 will initialised with zero.

    What's wrong ???

    If I add a secound variable that will located in register r5 and the init is in front of r4, like
      B530    push    {r4-r5,lr}
      2500    mov     r5,#0x00
      2400    mov     r4,#0x00
    
    and I break on init of r4 or later, then r5 is not zero in the register-window ???

  • 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