Time need to change external interrupt from disable to enable and vice versa

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

Time need to change external interrupt from disable to enable and vice versa

2,189 Views
akshaykatare
Contributor I

Hi,

I want to know how much time external interrupt need to change from disable(should never occur interrupt) to enable(to occur interrupt again) or vice versa.

I am using following method to enable and disable

PORTA_PCR13 ^= 10U<<16   //for disable

PORTA_PCR13 |= 10U<<16   //for enable

when I disable it and again enable it, sometimes it takes more time(I could not measure it) to occur interrupt again.

whether somebody know whether we need to wait for some time after enable and disable external interrupt?

Please let me know.

Thanks and regards,

Akshay

0 Kudos
Reply
8 Replies

1,978 Views
bobpaddock
Senior Contributor III

As Rastilav pointed out the code you are showing is probably not disabling the interrupt reliably.

This document explains the internals.  It is for the M1, it applies to the M0(+) as well:

http://infocenter.arm.com/help/topic/com.arm.doc.dai0211a/DAI0211A_interrupt_behaviour_of_cortexm1.p...

0 Kudos
Reply

1,978 Views
rastislav_pavlanin
NXP Employee
NXP Employee

Hi Akshay,

well the method you use for enabling/disableing ext. irq is a bit unusual. Not sure if negate the expression make sense to clearing the IRQ filied in 32-bit word. Is your expression PORTA_PCR13 ^= 10U<<16   //for disable really executed just ones after enabling the interrupt PORTA_PCR13 |= 10U<<16   //for enable?

We usually use this approach:

to set bits flied in register

       REGISTER |= REGISTER_BITFIELD_MASK;

or to clearbits flied in register

     REGISTER &= ~REGISTER_BITFIELD_MASK;

or your case example:

to enable PORTA_PCR13 = (PORTA_PCR13 & ~PORT_PCR_IRQC_MASK) | PORT_PCR_IRQC(0xA);

to disable PORTA_PCR13 = (PORTA_PCR13 & ~PORT_PCR_IRQC_MASK) | PORT_PCR_IRQC(0x0);

NOTE: Care must be taken with status flags which are cleared by reading!

regards

R.

0 Kudos
Reply

1,978 Views
bobpaddock
Senior Contributor III

"... to disable PORTA_PCR13 = (PORTA_PCR13 & ~PORT_PCR_IRQC_MASK) | PORT_PCR_IRQC(0x0); "

What is the actual point of doing the '& ~' style masking in assignment (=)?

It makes sense in some '&=' and '|=' contexts, not in assignment just wastes code space if the compiler is not optimizing it away.

0 Kudos
Reply

1,978 Views
egoodii
Senior Contributor III

'& ~' is specifically the way to 'and away' a group of bits, as defined by a header-mask, for which you need the 'inverse' to define which bits to KEEP.  The '| 0' in this statement is indeed a bit superfluous.  The other way to write this 'clear bits' is of course PORTA_PCR13 &= ~PORT_PCR_IRQC_MASK;  Your 'exclusive-or-equals' works ONLY if you KNOW that exactly that combo of bits were 'set' in that field prior to said statement, which sounds like a bit of a presumption.

By the way, are you specifically trying to ignore some external-pin interrupt conditions, or just 'delay them' to more opportune timing?  Is your part M0 or M4 core?

0 Kudos
Reply

1,978 Views
bobpaddock
Senior Contributor III

"'& ~' is specifically the way to 'and away' a group of bits, as defined by a header-mask, ..."

I understand the C code.

What I don't understand is why all this effort to mask things that are going to be overwritten by the assignment (=) anyway?


PORTA_PCR13 = (PORTA_PCR13 & ~PORT_PCR_IRQC_MASK) | PORT_PCR_IRQC(0x0);

and

PORTA_PCR13 = PORT_PCR_IRQC(0x0);

both have the same outcome. 

A good compiler will get rid of the useless mask, a bad one will waste a lot of space.

Masks in &= or |= may or may not be needed.  Not seeing a case where they are every needed in =.

0 Kudos
Reply

1,978 Views
egoodii
Senior Contributor III

I'm not quite sure where to go with this.  The appearance of PORTA_PCR13 on both sides of the '=' makes for a read-modify-write operation' (and same for the form &=, which is just shorthand for read-modify-write, AND for certain compilers and architectures makes it easier to make an efficient operation).  The register PORTA_PCR13 is read, 'anded' with the inverse-of-the-field-mask to 'zero' selected bits, and THEN assigned (written) back.  Given that PORT_PCR_IRQC_MASK is 0x000F0000, the inverse (~ operator, one's complement) will be 0xFFF0FFFF, so as to 'keep' the rest of the current register contents.

The net result of PORTA_PCR13 &= ~PORT_PCR_IRQC_MASK;  is:

PORTA_PCR13 = PORTA_PCR13 & 0xFFF0FFFF;

It is useful to remember that the 'C' language was created on a PDP-11, specifically to make it possible to write UNIX in 'something better than assembler' yet let compiler technology of the 70's create efficient output.  The PDP-11 HAD special read-modify-write instructions -- hence this assignment-form to let the compiler easily see the better sequence.  In a similar vein, 'conditional instruction execution' (also in ARM) led to the creation of the ? operator...

0 Kudos
Reply

1,978 Views
bobpaddock
Senior Contributor III

"The appearance of PORTA_PCR13 on both sides of the '=' makes for a read-modify-write operation ..."

I'm well versed in C.  Dig deep enough and you'll find my name in some GCC sources.

...

"It is useful to remember that the 'C' language was created on a PDP-11..."

These are photos I took of the Large Scale Systems Museum (LSSM), Dave McGuire President/Curator, in New Kensington Pennsylvania on January 30th 2016.  See the quick walk through video I made:

http://bpaddock.com/doku.php/lssm/start

Dave is expanding to two floors now.

If your in the area to see the LSS Museum we can debate the merit's of bit masks in contexts where they are not needed in person. :-)

0 Kudos
Reply

1,978 Views
egoodii
Senior Contributor III

I no longer even KNOW what us old-farts are even arguing about  :-)

All I CAN say is that if we come 'in' with PORTA_PCR13 as 0x00_04_01_77 (underscores are mine, of course) THEN

     PORTA_PCR13 = (PORTA_PCR13 & ~PORT_PCR_IRQC_MASK) | PORT_PCR_IRQC(0xA);

will make it into 0x00_0A_01_77 by clearing the appropriate nibble, then 'popping in' the 'A' there (falling edge mode), while

     PORTA_PCR13 = PORT_PCR_IRQC(0x0);

will make it all zero 0x00_00_00_00, disabling the pin (etc).

What the compiler can 'optimize away' is 'limited', at LEAST in this case, by the declaration of this (and MOST chip registers) as VOLATILE.

It is indeed worth re-iterating here an earlier warning about 'clearing control bits' using this kind of read-modify-write.  That is, IF this 'read' shows an active interrupt ISF, as in 0x01 in the first byte, THEN leaving that bit as a 'one' in your write-back WILL clear the interrupt on you, presumably 'unhandled'.  These 'write one to clear' register bits are especially tricky for that, and even Freescale boiler-plate code falls victim to it at times.  Other register-flag bits (in other contexts) can be cleared SIMPLY by 'reading'...  Finding such a 'very rare fault' that hits right in the 'problem window' is irritating indeed.

So what this 'enable' statement would REALLY need to be is:

      PORTA_PCR13 = (PORTA_PCR13 & ~(PORT_PCR_IRQC_MASK | PORT_PCR_ISF_MASK)) | PORT_PCR_IRQC(0xA);

so that we 'and off' a potential interrupt-status-indication as well.

Just to put the 'final nail' in this thing, this is a debug-listing/trace with added annotations:

PORTA_PCR13 = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK ;// Initialize PCR
0x424a: 0xf8df 0x093cLDR.W R1, ??DataTable76_16

; PORTA_PORTA_PCR13

  32bit constants are loaded PC-relative

0x424e: 0xf240 0x1143MOVW  R0, #323     ; 0x143 ;Short constant, in instruction
0x4252: 0x6001STR   R0, [R1]

PORTA_PCR13 = (PORTA_PCR13 & ~(PORT_PCR_IRQC_MASK | PORT_PCR_ISF_MASK)) | PORT_PCR_IRQC(0xA);//ENABLE PIN INTERRUPT
0x424e: 0xf8df 0x0938LDR.W R0, ??DataTable76_17

; 0xfef0ffff (-17760257)

This is our combined mask.

0x4252: 0x680aLDR   R2, [R1];Fetch port for RMW.  R2=0x143
0x4258: 0x4002ANDS  R2, R2, R0;Clear the IRQC bits, avoid ISF
0x425a: 0xf442 0x2220ORR.W R2, R2, #655360

; 0xa0000 ;'simple' constant, fits in instruction

R2=0x000A_0143

0x425e: 0x600aSTR   R2, [R1]; and finally the write-back
PORTA_PCR13 &= ~(PORT_PCR_IRQC_MASK | PORT_PCR_ISF_MASK);//DISABLE PIN INTERRUPT
0x4260: 0x680aLDR   R2, [R1]
0x4266: 0x4010ANDS  R0, R0, R2;This RMW just clears bits
0x4268: 0x6008STR   R0, [R1];R0 = 0x143
PORTA_PCR13 = PORT_PCR_IRQC(0);//CLEARS PCR
0x426a: 0x2000MOVS  R0, #0
0x426c: 0x6008STR   R0, [R1]; The simple 'assignment only' to ALL ZERO
0 Kudos
Reply