Bad design: no mask register for port interrupts

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

Bad design: no mask register for port interrupts

1,304 Views
paulderocco
Contributor III

I think in any future MCU series, Freescale needs to redesign the way port pin interrupts are handled slightly. What's missing is a 32-bit mask register. The only way you can prevent a request from a particular pin from being recognized is to disable it in the PORTx_PCRn register, but that's not the same thing as masking it because it discards any pending edge-detected interrupt. Also, you can't use the edge-detection logic to turn a pulse into a static level, and then poll it in software.

Instead of ORing the PORTx_ISFR bits together into the single NVIC input, PORTx_ISFR should be ANDed with a new 32-bit mask register at offset 0xA4 and then ORed into the NVIC. This would separate the definition of what constitutes a request (high level, low level, rising edge, falling edge, either edge), and the latching of edge-triggered interrupts, from the masking or unmasking of the interrupt. This would seem to me to be basic interrupt logic design--I'm surprised the designers got it wrong.

This can be fixed in software, but it's a bunch of work. For level sensitive interrupts, switch the individual pins to Disabled to mask them, and then switch them back to Logic 0 or Logic 1 to unmask them. For edge-sensitive interrupts, leave them all enabled, and have the interrupt handler "handle" those that are masked in software by setting deferred request bits for the masked interrupts in software, which would be invoked whenever they are later unmasked. Pretty ugly.

Tags (2)
0 Kudos
4 Replies

803 Views
chris_brown
NXP Employee
NXP Employee

Hi Paul,

I was hoping to get a little more information on your use case so that we may serve you better.  Is that possible?  I have never heard of a situation where this would be needed and I think if I understood your use case a little better I might be able to provide some additional assistance. 

For instance, I don't understand why you would want to have an edge sensitive interrupt masked.  True that masking it isn't the same as disabling and interrupt in the PORT PCR register but if your software isn't ready to handle that interrupt why would you want to keep that interrupt record?  And even if you had a need, you can enable an interrupt on the pin without enabling the Port in the NVIC and the interrupt routing wouldn't be executed. Otherwise, you could setup a counter variable to keep track of when the interrupt has been taken. Is it really that messy to setup a counter variable to keep track of when an edge sensitive interrupt has occurred?

As for turning a pulse into a static level, you are in essence creating what you want when you enable the edge sensitive interrupt.  An edge generated on that input pin sets the interrupt flag and that flag isn't cleared until your software clears it. So I'm again a little confused why you would want to do this and what exactly you mean by this? Do you need a pulse to create a static output on another pin?   

Sincerely,

Chris

0 Kudos

803 Views
paulderocco
Contributor III

For instance, I don't understand why you would want to have an edge sensitive interrupt masked.  True that masking it isn't the same as disabling and interrupt in the PORT PCR register but if your software isn't ready to handle that interrupt why would you want to keep that interrupt record?

Whether a request from an external device is pending has nothing to do with whether I'm ready to handle the request. Consider the obvious case of a device that processes bytes received from the program in some way, and indicates when it has finished processing a byte and is ready for another by pulsing an interrupt line. Just because it's ready for a byte doesn't mean I've got one to give it. The clean and simple way to handle that is to mask the interrupt when I no longer have any byte to issue to it. When the interrupt occurs, it just remains pending until I have another byte, at which point I can just unmask the interrupt, and bang, the interrupt happens and sends the next byte. If I have a software FIFO, the interrupt handler itself can do the masking when the FIFO becomes empty.

And even if you had a need, you can enable an interrupt on the pin without enabling the Port in the NVIC and the interrupt routing wouldn't be executed.

That would be exactly what I want, except that the single NVIC input is shared by all the pins on a port. With all the other devices, the individual interrupts that are combined into a single NVIC input have individual mask bits as part of the design of the device. (See for instance the UART, or SPI, or I2C.) That's the normal way of doing things.

Otherwise, you could setup a counter variable to keep track of when the interrupt has been taken. Is it really that messy to setup a counter variable to keep track of when an edge sensitive interrupt has occurred?

For edge-sensitive interrupts, it only takes a flag, not a counter. And that is indeed what I'm doing. It's two bits in software, a mask flag and a pending flag, and a few lines of code. When an interrupt occurs, the handler services the interrupt if the mask is clear, or sets the pending flag if the mask is set. When something clears the mask, it checks the pending flag, and simulates the "interrupt" at that time.

But it's only that simple if I require all inputs on the port to be edge-sensitive. If I wanted to construct a truly general purpose software wrapper for port interrupts, which handled both edge and level sensitive interrupts, it would have to treat them differently. It would treat edge-sensitive interrupts as described abbove, while level-sensitive interrupts would use the built-in disable mechanism, but would need a software record of what mode to put them in (high level or low level) when re-enabling them. That's pretty messy.

And the stock ExtInt PE component doesn't do any of this. It only really works for level-sensitive interrupts.

Oh, and another reason for being able to mask an edge-sensitive interrupt without disabling it is so that the request can be polled rather than invoking an interrupt handler, while still allowing other pin interrupts to be enabled.

Bottom line: to be consistent with all the other devices, all interrupts that are funneled through a single NVIC input should have independent masks. That's nothing more than another 32-bit register and 32 AND gates.

0 Kudos

803 Views
chris_brown
NXP Employee
NXP Employee

Hi Paul,

Thanks for elaborating on that.  This makes things a little clearer to me.  I have started an internal discussion and we'll see what comes of that.  I obviously can't guarantee that any changes will be made but I will keep you updated if anything comes of the internal discussion (be it a design change or just a more in depth explanation of why the pin interrupt logic was designed the way it was).

Again, I thank you for choosing Freescale and especially providing this valuable feedback.  We can't make improvements unless we hear feedback from customers.

Sincerely,

Chris

P.S.: If you like the service that I have provided, I would greatly appreciate it if you would click the "correct answer" button on my post. 

0 Kudos

803 Views
piotrek
Contributor III

Hello Chris,

I can learn something here.

You said:

An edge generated on that input pin sets the interrupt flag and that flag isn't cleared until your software clears it.

Is there a mechanism to have this flag masked not to generate an interrupt when the flag is set? This would be quite handy to check it programmatically or have an interrupt generated as soon as the mask is removed.

Regards,

Piotr

0 Kudos