Hi everyone
I'm trying to learn best practise with port interrupts for the M0+ chip I'm working with - the MKL25Z128VLK4 on the FRDM-KL15Z board. I'm using an external falling edge interrupt on PORTD Pin 4. It's all set up nicely using Processor Expert in CodeWarrior and I can correctly trigger into my PORTD ISR and test PORTD_PCR4 to determine the cause of the interrupt. So far so good. Since my ISR needs to trigger comms (which I can't do inside the ISR) I just test, clear and assert an asynchronous flag which I deal with elsewhere in the main loop. All works with this piece of code:
if(PORTD_PCR4 & 1<<24){
PORTD_PCR4 |= 1<<24; // 1 clears, not 0...
touchFlag = TRUE;
}
Easy, right? Except that it's not exactly ideal. It's using a non-atomic read-modify-write in the |= (along with the inline shift). This means that theoretically, another bit in the register could change between the read and the write. In this case it is unlikely (as each PCR only includes its own ISF) but I just wanted to see if there was a better way out there.
All thoughts gratefully received.
Stefan
Solved! Go to Solution.
Hi Stefan,
Theoretically, another bit could change, but since the chip really doesn't change the other bits in these registers dynamically (except in certain cases where the user doesn't have access to that particular functionality), they won't change unless you write them. So I don't think your concern is really anything to worry about.
You need the read, modify write unless you want to change all of the settings of the pin control register back to the default (which it doesn't sound like you do). Using PORTD_PCR4 = 1 << 24 will definitely change all of the other bits in the register (if they were something other than 0). The one thing I would suggest is that you use the masks in the Freescale header files. So if I were doing this, my code would be
if(PORTD_PCR4 & PORT_PCR_ISF_MASK){
PORTD_PCR4 |= PORT_PCR_ISF_MASK; // 1 clears, not 0...
touchFlag = TRUE;
}
This will eliminate the shift and reduce the number of instructions. It will also make your code more readable and intuitive.
Hope this helps,
Chris
Hi Stefan,
Theoretically, another bit could change, but since the chip really doesn't change the other bits in these registers dynamically (except in certain cases where the user doesn't have access to that particular functionality), they won't change unless you write them. So I don't think your concern is really anything to worry about.
You need the read, modify write unless you want to change all of the settings of the pin control register back to the default (which it doesn't sound like you do). Using PORTD_PCR4 = 1 << 24 will definitely change all of the other bits in the register (if they were something other than 0). The one thing I would suggest is that you use the masks in the Freescale header files. So if I were doing this, my code would be
if(PORTD_PCR4 & PORT_PCR_ISF_MASK){
PORTD_PCR4 |= PORT_PCR_ISF_MASK; // 1 clears, not 0...
touchFlag = TRUE;
}
This will eliminate the shift and reduce the number of instructions. It will also make your code more readable and intuitive.
Hope this helps,
Chris
Thanks Chris
I thought that I was probably worrying about nothing, but good to see the correct usage of the masks.
Thanks for your help!
Stefan
I am not sure that your concerns a re well founded, but in any even since 1 clears and 0 does nothing you can say:
PORTD_PCR4 = 1<<24;
The compiler will pre-compute 1<<24 so this should just be a constant.