Hi,   I'm converting over from using the IAR compiler for...

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Hi,   I'm converting over from using the IAR compiler for...

4,606 Views
electropw
Contributor III
Hi,
 
I'm converting over from using the IAR compiler for the HCS12.
 
I have found that CodeWarrior does not support a nifty function generation attribute called "__monitor".
 
This attribute causes the function to generate code to, on entry, save the current interrupt enable status & disable interrupts; then, on exit, restore the saved interrupt enable status.
 
This is a really useful tool.
 
Does anyone know of an implementation work around for CodeWarrior or whether Freescale intends to support this functionality?
 
regards
PhilW
 
Labels (1)
Tags (1)
0 Kudos
Reply
10 Replies

2,471 Views
Lundin
Senior Contributor IV
If you mean the global interrupt enable/disable (the "I" bit in the condition code register), this is done by the hardware.

If you mean the cause of the interrupt, there is no support for it as far as I know. There is no big deal looking it up yourself, since you need to know how every interrupt work anyway. They all tend to be somewhat different, and so is the way to clear the interrupt flags.
0 Kudos
Reply

2,471 Views
bigmac
Specialist III
Hello Phil,
 
I am not sure whether this provides what you require -
 
void func( void)
{
   __asm  pshc;  // Save current CCR state
   __asm  sei;   // Disable interrupts
 
  /* Function code here */
 
   __asm  pulc;  //  Restore previous CCR state
}
 
 
Regards,
Mac
 
0 Kudos
Reply

2,471 Views
electropw
Contributor III
Hi Mac,
 
Thanks for your reply. Yes I tried this, created a coupla macros to do it.
 
Unfortunately it is not versatile enough unless you have a simple function that falls straight through or you write your code specifically to support the macro insertions.
 
For example you may try
 
char function ( a,b )
{
   SaveIEstatusDisableI;
 
   return a + b;
 
   RestoreIEStatus;
}
 
This will not work since the compiler automatically generates the return code in the return statement and then inserts the macro code following it, and it will never be executed.
 
 
The beauty of the IAR __monitor keyword is that it does the IE status saving and resoration automatically, no matter how many return statements you may have within your function.
 
regards
Phil
 
0 Kudos
Reply

2,471 Views
bigmac
Specialist III
Hello Phil,
 
In this case, you would need to place the restore macro just prior to each return statement.  Or perhaps create another macro that provides both the restore and return process.
 
#define _critical           __asm  pshc; __asm  sei;
#define _critical_return(x) __asm  pulc; return(x);
 
Obviously not quite as convenient as having a special compiler specific keyword available.
 
Regards,
Mac
 
0 Kudos
Reply

2,471 Views
electropw
Contributor III
Hi Mac,
 
Bugger!!!!
 
will not work either, very close though.
 
Will depend in what you are doing in the code as to how you would implement the use.
 
To explain, One of the uses I had in mind was to protect a global variables value whilst reading it or writing it, either in an IRQ or in a background access.
 
int read_x( int x )
{
    return x;
}
 
This produces code, LDD x; RTS.
 
 
With our solution
 
int read_x( int x )
{
    _critical
    _critical_return (x)
}
 
produces
 
    PSHC
    SEI
    PULC
    LDD x
    RTS
 
A pointless operation huh!
 
We would have to try and maybe load a local with x and return the local and then ensure the compiler
does not optimize out our uae of the local.
 
 
I have contacted CodeWarrior and they tell me they will look at it and put it on the requested functionality
list. So no immediate nice solution, if there ever will be.
 
I might try and see if I can do some sort of  macro function call and embedd our solution in there, maybe!!
 
regards
Phil
 
0 Kudos
Reply

2,471 Views
bigmac
Specialist III
Hello Phil,
 
The LDD x instruction would represent the compiler output corresponding with the return(x); statement, for a 16-bit return value.  So the assembly code is what might be expected.
 
Passing the current value of a global variable to the function, via the parameter x will simply result in the return of that value, independent of what a subsequent interrupt may do to the contents of the global variable.
 
If you needed to prevent the occurrence of an interrupt altering a global variable whilst a function manipulates its value, and then to return the newly modified value, the following approach might work -
 
int g_var1;
 
int func( int y)
{
   _critical;
   g_var1 += y;
   y = g_var1;
  _critical_return(y);
}
 
You could not use the statement _critical_return(g_var1); since an interrupt might possibly occur between the PULC and the LDD instructions.
 
Regards,
Mac
 


Message Edited by bigmac on 2008-03-20 04:22 PM
0 Kudos
Reply

2,471 Views
electropw
Contributor III
Hi Mac,
 
Exactly what I was trying to say above.
 
I also know that the IAR compiler is, I imagine also CW to be also, smart enough to optimise out the y=g_var1; statement and just return g_var1. This effectively nulifies what we were trying to do.
 
Please note that my sample was simply that, a sample. Just shown to simply describe the compiler operation. I know in real life with the HC12 that there is no need to protect int sized variables in such operations since it is a single instruction operation and therefore cannot be corrupted by an interrupt occuring during the access. The ones of concern are the variables > 2 bytes in size.
 
regards
Phil
 
0 Kudos
Reply

2,471 Views
bigmac
Specialist III
Hello Phil,
 
It might be sufficient to declare the global variable as -
 
volatile int g_var1;
 
to prevent that sort of optimisation by the compiler.  I guess all global variables that are referenced within ISRs should normally be declared as volatile.
 
Regards,
Mac
 
0 Kudos
Reply

2,471 Views
bigmac
Specialist III
Hello again Phil,
 
I adapted the macros for HC08 MCU (which I am more familiar with) and then tested the following function to return the value of a long variable -
 
long g_var1 = 10000L;
 
long getlong( volatile long *ptr)
{
   long temp;
   _critical;
   temp = *ptr;
   _critical_return(temp);
}
 
long b;
b = getlong( &g_var1);
 
There didn't appear to be optimisation by the compiler in the manner that you suggested.  I also tried a similar function to return a short value, which is also critical for an 8-bit device, with similar results.
 
Regards,
Mac
 


Message Edited by bigmac on 2008-03-20 07:46 PM
0 Kudos
Reply

2,471 Views
electropw
Contributor III
Hi Mac,
 
Good idea.
 
I'll try it.
 
Thanks again.
 
0 Kudos
Reply