Search code examples
cmacrosescapingarmcc

C Macro utilizing immediate values in embedded arm asm - armcc


The closest threads to my question are these Escaping a # symbol in a #define macro? and How to print a pound / hash via C preprocessor?, but they don't exactly answer my question. More explicitly, the second doesn't seem to work with the armcc compiler; it just prints hash4 and not the symbol defined by hash. Chris Lutz was especially disparaging of trying use a macro for this functionality in the second post, so maybe this is the incorrect method all together. I would like more thoughts than just one persons, though.

The problem is the following: I'm trying to write a macro that defines an embedded asm C function utilizing a macro. I've essentially implemented it except for one issue... expressing an immediate value. Immediate values' syntax requires (I believe) a pound symbol which is also the "stringify" symbol for the preprocessor. So, is it possible to escape a # symbol in a C macro?

The primary purpose behind this is to wrap an isr with a pico kernels thread context management procedures and that new procedure's function pointer will eventually be passed to the vectored interrupt controller.

Here's the code:

#define ISR_THREAD_MGMT(ISR_FUNC,FUNC_NAME) \
__asm void FUNC_NAME ( void ); \
__asm void FUNC_NAME (void ) \
{ \
    STMDB sp!, {r0-r3}; \
    MRS   r0, SPSR; \
    SUB   lr, lr, #4; \        <----- Heres the problem
    STMDB sp!, {r0, r10, r12, lr}; \
    bl _thread_vectored_context_save; \
    bl ISR_FUNC; \
    b _thread_context_restore; \
}

I hope I've explained everything in sufficient detail. If not, please don't hesitate to ask for any more details.


Solution

  • The second of your referenced questions shows you how to do it:

    #define hash #
    #define mash(x) x
    #define immediate(a) mash(hash)a
    #define ISR_THREAD_MGMT(ISR_FUNC,FUNC_NAME) \
    __asm void FUNC_NAME ( void ); \
    __asm void FUNC_NAME ( void ) \
    { \
        STMDB sp!, {r0-r3}; \
        MRS   r0, SPSR; \
        SUB   lr, lr, immediate(4); \
        STMDB sp!, {r0, r10, r12, lr}; \
        bl _thread_vectored_context_save; \
        bl ISR_FUNC; \
        b _thread_context_restore; \
    }
    
    ISR_THREAD_MGMT(abc,def)
    

    Output:

    # 1 "x.c"
    # 1 "<command-line>"
    # 1 "x.c"
    # 17 "x.c"
    __asm void def ( void ); __asm void def ( void ) { STMDB sp!, {r0-r3}; MRS r0, SPSR; SUB lr, lr, #4; STMDB sp!, {r0, r10, r12, lr}; bl _thread_vectored_context_save; bl abc; b _thread_context_restore; }
    

    Output reformatted:

    # 1 "x.c"
    # 1 "<command-line>"
    # 1 "x.c"
    # 17 "x.c"
    __asm void def ( void );
    __asm void def ( void )
    {
        STMDB sp!, {r0-r3};
        MRS r0, SPSR;
        SUB lr, lr, #4;
        STMDB sp!, {r0, r10, r12, lr};
        bl _thread_vectored_context_save;
        bl abc;
        b _thread_context_restore;
    }
    

    I'm not convinced it is a good idea, but it does at least work.