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

Interworking Thumb-Mode Assembly Module -- How?

Hi All.

I'm having difficulty creating a Thumb-mode assembly language module that will successfully link in a uVision3+CARM project that is compiled in ARM mode.

The module compiles, links and works fine with the rest of the project when everything is built in Thumb mode.

Since CARM's calling convention and the module's internals conform with the ARM interworking veneer (or whatever it's called), it would seem to me that I could add

PUBLIC FnName?A
FnName?A


to the existing

PUBLIC FnName?T
FnName?T PROC CODE16


in the Thumb assembly module so that the linker has an ARM-mode entry point into the function as well as its Thumb-mode entry point. But the function itself is purely Thumb mode, of course.

Since the function is BL'd to, and the assembly module is written in Thumb and the function is EXEC16 (Thumb), its address is odd ([0]=1), and so the processor will successfully switch to Thumb mode from ARM when it executes the function via BL.

Unfortunately, I'm having problems with the linker. Specifically, it's reporting alignment errors in other C modules in the project, if I build the entire project in ARM mode. Building in Thumb mode succeeds.

The ARM docs (from ARM, not Keil) specifically mention an ALIGN assembler directive (see STM/LDM instruction summary examples). It seems to me that this might be the solution to my problem, if my problem is indeed due to a non-word alignment due to Thumb-mode instructions in an otherwise ARM build.

Can anyone help?

Thanks,

Parents
  • Correction:

    $IF (MAKE_FOR_ARM = 1)
    $IF (MAKE_FOR_INTERWORK = 1)
                    PUBLIC      myfunc?T
    myfunc?T        PROC        CODE16      ; Thumb entry, ARM mode
                    BX          PC
                    NOP
                    ENDP
    $ENDIF
                    PUBLIC      myfunc?A
    myfunc?A        PROC        CODE32      ; ARM entry, ARM mode
    $ELSE
    $IF (MAKE_FOR_INTERWORK = 1)
                    PUBLIC      myfunc?A
    myfunc?A        PROC        CODE32      ; ARM entry, Thumb mode
                    ADR         R0,myfunc?T
                    BX          R0
                    ENDP
    $ENDIF
                    PUBLIC      myfunc?T
    myfunc?T        PROC        CODE16      ; Thumb entry, Thumb mode
    $ENDIF
                    ...
                    BX          LR
    
                    ENDP

Reply
  • Correction:

    $IF (MAKE_FOR_ARM = 1)
    $IF (MAKE_FOR_INTERWORK = 1)
                    PUBLIC      myfunc?T
    myfunc?T        PROC        CODE16      ; Thumb entry, ARM mode
                    BX          PC
                    NOP
                    ENDP
    $ENDIF
                    PUBLIC      myfunc?A
    myfunc?A        PROC        CODE32      ; ARM entry, ARM mode
    $ELSE
    $IF (MAKE_FOR_INTERWORK = 1)
                    PUBLIC      myfunc?A
    myfunc?A        PROC        CODE32      ; ARM entry, Thumb mode
                    ADR         R0,myfunc?T
                    BX          R0
                    ENDP
    $ENDIF
                    PUBLIC      myfunc?T
    myfunc?T        PROC        CODE16      ; Thumb entry, Thumb mode
    $ENDIF
                    ...
                    BX          LR
    
                    ENDP

Children
  • Here is the opposite example: Thumb Function which may be called from Thumb or ARM Code

    AREA   ?PR?myfunc, CODE, READONLY, ALIGN=2
    
    PUBLIC myfunc?T, myfunc?A
    
    myfunc?A   PROC    CODE32	; ARM entry
               LDR     R12,[R15]
               BX      R12
               DD      myfunc?T
               BX      PC
               NOP
               ENDP
    
    myfunc?T   PROC    CODE16       ; ARM entry
               PUSH    {R4, LR}     ; save required registers
    
    RETURN:    POP     {R4}         ; restore registers
               POP     {R3}
               BX      R3           ; return to ARM or Thumb code
               ENDP