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
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:
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.
"... 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.
'& ~' 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?
"'& ~' 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 =.
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...
"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. :-)
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 0x093c | LDR.W R1, ??DataTable76_16 | ; PORTA_PORTA_PCR13 32bit constants are loaded PC-relative | |
0x424e: 0xf240 0x1143 | MOVW R0, #323 | ; 0x143 ;Short constant, in instruction | |
0x4252: 0x6001 | STR R0, [R1] |
PORTA_PCR13 = (PORTA_PCR13 & ~(PORT_PCR_IRQC_MASK | PORT_PCR_ISF_MASK)) | PORT_PCR_IRQC(0xA); | //ENABLE PIN INTERRUPT | ||
0x424e: 0xf8df 0x0938 | LDR.W R0, ??DataTable76_17 | ; 0xfef0ffff (-17760257) This is our combined mask. | |
0x4252: 0x680a | LDR R2, [R1] | ;Fetch port for RMW. R2=0x143 | |
0x4258: 0x4002 | ANDS R2, R2, R0 | ;Clear the IRQC bits, avoid ISF | |
0x425a: 0xf442 0x2220 | ORR.W R2, R2, #655360 | ; 0xa0000 ;'simple' constant, fits in instruction R2=0x000A_0143 | |
0x425e: 0x600a | STR R2, [R1] | ; and finally the write-back | |
PORTA_PCR13 &= ~(PORT_PCR_IRQC_MASK | PORT_PCR_ISF_MASK); | //DISABLE PIN INTERRUPT | ||
0x4260: 0x680a | LDR R2, [R1] | ||
0x4266: 0x4010 | ANDS R0, R0, R2 | ;This RMW just clears bits | |
0x4268: 0x6008 | STR R0, [R1] | ;R0 = 0x143 | |
PORTA_PCR13 = PORT_PCR_IRQC(0); | //CLEARS PCR | ||
0x426a: 0x2000 | MOVS R0, #0 | ||
0x426c: 0x6008 | STR R0, [R1] | ; The simple 'assignment only' to ALL ZERO |