Masking interrupts?

Scott Howard scott@objsw.com
Fri Jul 2 23:46:00 GMT 1999


Try this:

asm (" ori.l %1,%0" : "=m" (EZ328_IMR) : "i" (EZ328_INT_UART));

The compiler fills in the %0 and %1 parameters with the specified data,
according to the constraints "m" (memory address) and "i" (immediate
data). Pretty cool eh?

The following code is output:

  39 000a 307C F304 		move.w #-3324,%a0
  40               	#APP
  41 000e 0090 0000 		 ori.l #4,(%a0)
  41      0004
  42               	#NO_APP

Still not the best it could be, but it will work.

For all the details on the weird & wonderful 'asm' syntax, have a look
at http://www.objsw.com/docs/gcc_86.html#SEC86

Scott

David Williams wrote:
> 
> Hi All,
> 
> I am using ECGS 1.1.1 for M68K-coff, on win95 host (binaries supplied by
> http://www.objsw.com/ ).
> 
> I have found that the following code to mask an interrupt in the interrupt
> mask register of the processor I am using (68EZ328) has a problem.
> 
> #define EZ328BASE               0xFFFFF000
> #define EZ328_IMR               (*(volatile lword *)(EZ328BASE+0x304))  /* Interrupt Mask
> Reg */
> #define EZ328_INT_UART  0x00000004
> ...
>         EZ328_IMR |= EZ328_INT_UART;
> ...
> 
> The compiler produces code that reads the value of the interrupt mask
> register into a processor register. It then or's the constant with the
> value in the processor register and then writes the value back into the
> interrupt mask register. The problem is that there is a chance (even though
> quite small) that an interrupt could go off between reading the current
> value of the interrupt mask register and writing back the new value. This
> is a problem for me as I have an interrupt that modifies the value of the
> mask register from time to time.
> 
> What I want the compiler to do is to modify the interrupt mask register
> directly in an atomic operation. If the compiler used the ORI instruction
> then it would work as this instruction allows a memory location to be
> modified with one instruction (intrinsically atomic). However it doesn't
> use this instruction it uses a three instruction sequence to read modify
> write the register.
> 
> So what to do. My only though thus far is to use some in-line assembly to
> ensure that the correct code (for me) is generated. Then I ran into the
> following problems.
> 
> I first tried:
> #define EZ328BASE               0xFFFFF000
> #define EZ328_IMR               (EZ328BASE+0x304)       /* Interrupt Mask Reg */
> #define EZ328_INT_UART  0x00000004
> 
> ...
>         asm("   ORI.L #EZ328_INT_UART, EZ328_IMR" );
> ...
> 
> This didnt work. The linker complains that EZ328_INT_UART and EZ328_IMR are
> undefined symbols. The problem I see is that the preprocessor runs on the C
> code and doesn't look inside the assembly statement string to replace the
> names with the actual values.
> 
> So then I tried using the stringization of the constants as follows
> 
> #define EZ328BASE               0xFFFFF000
> #define EZ328_IMR               (EZ328BASE+0x304)       /* Interrupt Mask Reg */
> #define EZ328_INT_UART  0x00000004
> #define toStr(x) #x
> 
> ...
>         asm("   ORI.L #" toStr(EZ328_INT_UART) ", " toStr(EZ328_IMR));
> ...
> This didn't change anything. The preprocessor produced the same thing!
> 
> Obviously I could just insert the value of the constants directly into the
> string however this is not very maintainable. If I do have to use in-line
> assembly I would prefer that it is maintainable.
> 
> Can anyone suggest a way of solving my problem either by using in-line
> assembly or some other method?
> 
> TIA.
> David Williams.
> DLC software P/L
> davidwilliams@ozemail.com.au
> 
> _______________________________________________
> New CrossGCC FAQ: http://www.objsw.com/CrossGCC
> _______________________________________________
> To remove yourself from the crossgcc list, send
> mail to crossgcc-request@cygnus.com with the
> text 'unsubscribe' (without the quotes) in the
> body of the message.
_______________________________________________
New CrossGCC FAQ: http://www.objsw.com/CrossGCC
_______________________________________________
To remove yourself from the crossgcc list, send
mail to crossgcc-request@cygnus.com with the
text 'unsubscribe' (without the quotes) in the
body of the message.


More information about the crossgcc mailing list