This is the mail archive of the crossgcc@cygnus.com mailing list for the crossgcc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Masking interrupts?


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.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]