Yahoo Groups archive

Lpc2000

Index last updated: 2026-04-28 23:31 UTC

Message

Re: Example of C and inline ASM in a file?

2006-04-14 by John Heenan

Despised by the 'beautiful people' but practical, macros make it is 
easy to retarget ARM inline assembler to work with C code compiled as 
Thumb assembler.

Following are expamples for interrupt disable/enable for GCC. The 
intention is simply to force the macros through functions compiled as 
ARM code so as the compiler will force correct usage of bx to switch 
between ARM and Thumb modes, when compiling Thumb code. The beauty of 
the macro system is that all ARM generated code can use pure inline 
assembler through
#define INTDISABLE INTIF_DISABLE
#define INTENABLE  INTIF_ENABLE
and all Thumb generated code can use function wrappers for the same 
macro names through
#define INTDISABLE cpsr_if_disable()
#define INTENABLE  cpsr_if_enable()

When it comes to portability, the interface definiton is crucial. 
Macros make it dead easy to muck around with interface defintions. Of 
course debugging through a macro maze is another story!

//part of HEADER FILE such as header.h

//MAKE SURE A DEFAULT ISR HANDLER IS ASSIGNED TO VICDefVectAddr
//THE DEFAULT ISR HANDLER CAN BE EMPTY BUT MUST BE PRESENT
#define INTDISABLE INTIF_DISABLE
//#define INTDISABLE cpsr_if_disable()
#define INTENABLE  INTIF_ENABLE
//#define INTENABLE  cpsr_if_enable()

#define SLOWINTDISABLE INTI_DISABLE
//#define SLOWINTDISABLE cpsr_i_disable()
#define SLOWINTENABLE  INTI_ENABLE
//#define SLOWINTENABLE  cpsr_i_enable()

//volatile definition forces stack storage and is not required
//as optimisation sees variable is used by a function and so keeps
//#define INTVAR volatile int cpsr_prior
#define INTVAR int cpsr_prior
#define INTGETDISABLE cpsr_prior=cpsr_ifget_disable()
#define INTRESTORE cpsr_c_restore(cpsr_prior)

void cpsr_if_disable(void); //works with thumb
void cpsr_if_enable(void);  //works with thumb  
void cpsr_i_disable(void); //works with thumb
void cpsr_i_enable(void);  //works with thumb  

int cpsr_ifget_disable(void);//works with thumb
void cpsr_c_restore(int cpsr_prior);//works with thumb


//not OK for thumb code
#define INTIF_ENABLE   asm volatile ( \
   "mrs r3,cpsr     \n\t" \
   "bic r3,r3,#0xC0 \n\t" \
   "msr cpsr_c,r3   \n\t" \
   :                      \
   :                      \
   : "r3"                 \
)

#define INTIF_DISABLE  asm volatile ( \
   "mrs r3,cpsr		\n\t" \
   "orr r3,r3,#0x80 \n\t" /* I bit. separate disablement: see user 
manual */ \
   "msr cpsr_c,r3   \n\t" \
   "orr r3,r3,#0x40 \n\t" /* F bit */ \
   "msr cpsr_c,r3   \n\t" \
   :                      \
   :                      \
   : "r3"                 \
)

#define INTI_ENABLE   asm volatile ( \
   "mrs r3,cpsr     \n\t" \
   "bic r3,r3,#0x80 \n\t" \
   "msr cpsr_c,r3   \n\t" \
   :                      \
   :                      \
   : "r3"                 \
)

#define INTI_DISABLE  asm volatile ( \
   "mrs r3,cpsr     \n\t" \
   "orr r3,r3,#0x80 \n\t" \
   "msr cpsr_c,r3   \n\t" \
   :                      \
   :                      \
   : "r3"                 \
)


//MODULE FILE compiled as ARM assembler
#include "header.h"

void cpsr_if_disable(void)//works from thumb
{
 INTIF_DISABLE;
}

void cpsr_if_enable(void)//works from thumb
{
  INTIF_ENABLE;
}

void cpsr_i_disable(void)//works from thumb
{
  INTI_DISABLE;
}

void cpsr_i_enable(void)//works from thumb
{
  INTI_ENABLE;
}

int cpsr_ifget_disable(void)//works from thumb
{
  unsigned int cpsr_prior;
  asm volatile (
   "mrs %0, cpsr       \n\t"
   "orr r3, %0, #0x80  \n\t"  /* I bit. separate disablement: see 
user manual */
   "msr cpsr_c, r3     \n\t" 
   "orr r3, r3, #0x40  \n\t"  /* F bit */
   "msr cpsr_c, r3     \n\t"
    : "=r"(cpsr_prior)
    :
    : "r3"
  );
  return cpsr_prior;
//assmembler generated
// mrs r0, cpsr       
// orr r3, r0, #0x80  
// msr cpsr_c, r3     
// orr r3, r3, #0x40  
// msr cpsr_c, r3     
// bx	lr
}

void cpsr_c_restore(int cpsr_prior)//works from thumb
{
  asm volatile (
   "msr cpsr_c, %0 \n\t"
    :
    : "r" (cpsr_prior)
  );
//assembler generated
// msr cpsr_c, r0  
// bx	lr
}


John Heenan


--- In lpc2000@yahoogroups.com, "brendanmurphy37" 
<brendan.murphy@...> wrote:
>
> 
> Jaya,
> 
> OK - I give up. I've clearly failed to explain to you the point I 
was 
> trying to make (which has nothing to do with interworking or 
whether 
> or not particular features are supported by GCC). Maybe someone 
else 
> can try.
> 
> Hopefully others will have understood what I've been trying to say, 
> and it'll provide them some food for thought.
> 
> Brendan
> 
> --- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@> wrote:
> >
> > Dear Brendan,
> > 
> > This dialog has gone long enough.  I like to finish off by 
> addressing
> > your lingering doubts once more as best as one can, and move on.
> > 
> > --- In lpc2000@yahoogroups.com, "brendanmurphy37" 
<brendan.murphy@>
> > wrote:
> > 
> > > Consider the following sequence of events:
> > > 
> > > 1. We need some mechanism to lock out interrupts, for reasons 
> that 
> > > should be clear enough to everyone.
> > > 
> > > 2. We decide to implement this as in-line assembler, wrapped up 
> in 
> > > some nice macros. In fact, we implement exactly the same macros 
> as 
> > > you presented in your example.
> > > 
> > > 3. We test these out, and they work well. Everyone is delighted 
> with 
> > > the results. Our macros are a great sucess, and everyone is 
> happy. 
> > > Everyone uses them, all over the place.
> > 
> > Thus my on-the-fly example has served its purpose.
> > 
> > > 4. Then, as often happens, some new requirement comes along. 
Code 
> > > space is now a real issue for everyone. No problem: our chosen 
> > > architecture has just the solution: re-build all our software 
> using 
> > > Thumb mode.
> > > 
> > > 5. We re-build our software and are faced with an immediate 
> problem: 
> > > our nice macros that are used everywhere no longer work, as 
they 
> use 
> > > ARM-mode specific instructions.
> > > 
> > > How do we solve this problem? there are all sorts of ways it 
can 
> be 
> > > solved: I'm sure you and I could both come up with several 
> without 
> > > too much effort. The problem is that it will take effort, no 
> matter 
> > > how it's done.
> > 
> > You cannot turn off interrupts while in thumb mode if you do not
> > interwork. 
> > 
> > > The point I'm making is that the more you use non-standard, 
> compiler-
> > > specfic features such as in-line assembler, the more likely it 
is 
> > > that changing requirements will cause problems.
> > 
> > GCC supports interworking.  It has compiler options to select the
> > paradigm you want to adopt for interworking.  If you do not want 
to
> > use it because it is not supported in the same way on all 
compilers,
> > that is up to you.
> > 
> > I like to use the feature given I think GCC supports it well 
enough.
> > 
> > > I completely take your point that your example was for 
> illustrative 
> > > purposes only, and that you probably wouldn't implement these 
> macros 
> > > in a working system (possibly for the reasons I outline).
> > 
> > This is not what I said.  I stand by what I said.
> > 
> > Finally Brendan, my on-the-fly example having served its purpose, 
> and
> > the forum having moved on, it is about time you do the same.
> > 
> > Jaya
> >
>

Attachments

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.