MCF5235 Interrupt enable/disable spuriousity

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

MCF5235 Interrupt enable/disable spuriousity

1,211 Views
richardwielend
Contributor I

I have a problem when enabling/disabling single EPORT-Interrupts.

I do it this way:

void EPORT::InterruptOn() /*-FUNCTION HEADER-------------------------------------------------------- | description : enables a certain interrupt | side effects : | parameters : | return value : none | precondition : | postcondition: +--END FUNCTION HEADER--------------------------------------------------*/ { MCF_EPORT_EPIER |= MCF_EPORT_EPIER_EPIEx(m_byPortNr); } void EPORT::InterruptOff() /*-FUNCTION HEADER-------------------------------------------------------- | description : disables a certain interrupt | side effects : | parameters : | return value : none | precondition : | postcondition: +--END FUNCTION HEADER--------------------------------------------------*/ { MCF_EPORT_EPIER &= ~MCF_EPORT_EPIER_EPIEx(m_byPortNr); }

Do you have an idea what I´m doing wrong?

The behavior is like that:

When I disable a certain interrupt other interrupts also get disabled, not all of them, just some, and those are always the same.

For example when I disable port:1 -> port:3 also gets disabled

or                              disable Port:3 -> port:5 also gets disabled

or                              disable Port:5 -> port:3 also gets disabled

or                              disable Port:7 -> port:1 also gets disabled

I really would appreciate some help :smileyhappy:

regards, Richard

0 Kudos
12 Replies

953 Views
richardwielend
Contributor I

For sure I meant: " I have not found the "Syntax highlighter" button... previously" :smileygrin:

So I found it with your help, thanks :smileyhappy:

>They MUST be different for every separate interrupt source, and that includes every EPORT. All seven of them have to unique Priority:Level. So if you want all EPORTs at the the same level, then they have to have priorities 1, 2, 3, 4, 5, 6, 7.

Yeah I wrote the settings are:

USB_Read: m_byInterruptLevel:1 m_byInterruptPriority:1

Button_OFF: m_byInterruptLevel:2 m_byInterruptPriority:2

Button_OPEN: m_byInterruptLevel:3 m_byInterruptPriority:3

TRIGGER: m_byInterruptLevel:5 m_byInterruptPriority:5

EPFn is written a level above, so you can´t see it in that routines.

So .. I´m pretty sure it´s a fluke, as you can see in the attached picture.

And the last thing you suggested, I have to admit that I haven´t got what you wanted to explain :smileysad: Could you reexplain it another way ? :smileyhappy:

best, Richard

0 Kudos

953 Views
TomE
Specialist II

> So .. I´m pretty sure it´s a fluke, as you can see in the attached picture.

There's no "attached picture". Could you try again, or say what's in the picture as text?

> And the last thing you suggested, I have to admit that I haven´t got what you wanted to explain

The last thing I suggested was that you delete the duplicate post. So I assume you mean the second-last thing. But it would help if you'd have said which thing.

So I have to guess you are referring to my numbered-list 1-7. Do you mean all of that or just the last item it that?

I'm suggesting you read the EPORT control registers and print their numeric values either side of when it works and when it doesn't.

> USB_Read: m_byInterruptLevel:1 m_byInterruptPriority:1

> Button_OFF: m_byInterruptLevel:2 m_byInterruptPriority:2

I wouldn't recommend different levels AND priorities. You should normally have all "similar interrupts" that are being handled similarly at the same level, distinguished by priority. That way they can't accidentally interrupt each other.

Tom

0 Kudos

953 Views
richardwielend
Contributor I

Yeah I meant the bullet points :smileyhappy: Now I got it, thank you, I will try this.

0 Kudos

953 Views
TomE
Specialist II

There's another thing that is very commonly gotten wrong.

Interrupt handling is like the little/big-endian problems. If it doesn't scare you then you don't understand it properly :-)

Most chip manufacturers get interrupt handing badly wrong. Motorola got it dead right. Maybe they patented "the one true solution" so nobody else could use it, or maybe the other manufacturers didn't realise the True Majesty of Motorola's Solution. Which carried over into most of Freescale's parts.

The "solution" is called "W1C".

If you don't know how insanely great this is then you might not be using it properly, and so your problem may not be the interrupt setting, but in your interrupt service code.

Of course I've detailed this before, so I suggest you read through this post to see if it shows up any problems in your interrupt handler.

https://community.nxp.com/message/105778?commentID=105778#comment-105778

If dumping the registers around your setting code doesn't show the problem then it might be with your use of W1C.

Tom

0 Kudos

953 Views
richardwielend
Contributor I

20170717_145105.jpg

0 Kudos

953 Views
richardwielend
Contributor I
#define MCF_INTC0_ICRn(x)      (*(vuint8 *)(void*)(&__IPSBAR[0x000C40+((x)*0x001)]))
#define MCF_INTC0_ICRn_IP(x)          (((x)&0x07)<<0)
#define MCF_INTC0_ICRn_IL(x)          (((x)&0x07)<<3)
0 Kudos

953 Views
TomE
Specialist II

You seem to have created a second post with the same SUBJECT as your original one. Maybe you created it "as new" rather than using the "Reply" buttons in this one. Can you delete the other one as I think I've answered your quesionn in this thread. I think there's a "Delete" option under the "Actions" button on the lower left of the page.


Tom

0 Kudos

953 Views
richardwielend
Contributor I

Yes, pretty sure.

So the Initialization looks like this:

void
EPORT::Init()
/*-FUNCTION HEADER--------------------------------------------------------
|   description  : Initialize GPIO
|   side effects :
|   parameters   :
|   return value : none
|   precondition :
|   postcondition:
+--END FUNCTION HEADER--------------------------------------------------*/
{
     MCF_EPORT_EPPAR |= MCF_EPORT_EPPAR_EPPAx(m_byPortNr, m_byEdgeDetect);
     if (m_bOutput)
          MCF_EPORT_EPDDR |= MCF_EPORT_EPDDR_EPDDx(m_byPortNr);
     else
          MCF_EPORT_EPDDR &= ~MCF_EPORT_EPDDR_EPDDx(m_byPortNr);

//     MCF_EPORT_EPDDR |= MCF_EPORT_EPPAR_EPDDx(m_byPortNr, m_bOutput);
     if(m_byInterruptLevel > 0 && m_byInterruptPriority > 0)
     {          
// disable Interrupts     ?     
          mcf523x_irq_disable();          
// Set Interrupt Control Register 
          MCF_INTC0_ICRn(m_byPortNr) = MCF_INTC0_ICRn_IL(m_byInterruptLevel) | MCF_INTC0_ICRn_IP(m_byInterruptPriority);
// Clear Interrupt Mask Bits
          MCF_INTC0_IMRL &= ~MCF_INTC0_IMRL_MASKALL;                    // bit 0 = mask All bit =>UnMask
          MCF_INTC0_IMRL &= ~MCF_INTC0_IMRL_INT_MASK(m_byPortNr);     // UnMask Bit m_byPortNr = EPORTx
// enable Interrupt at all
          mcf523x_irq_enable();           
     }     
}

And the m_byInterruptLevel and m_byInterruptPriority are for every EPORT the same but for Port to Port different.

Like that:

USB_Read: m_byInterruptLevel:1 m_byInterruptPriority:1

Button_OFF: m_byInterruptLevel:2 m_byInterruptPriority:2

Button_OPEN: m_byInterruptLevel:3 m_byInterruptPriority:3

TRIGGER: m_byInterruptLevel:5 m_byInterruptPriority:5

0 Kudos

953 Views
TomE
Specialist II

> I have not found the "Syntax highlighter" button...

You found something that let you format your code well. How did you do it?

To get to "Syntax Highlighter":

1 - Click on "Use advanced editor" at the top-right of the edit window,

2 - The Toolbar (B I = = " Ix Chain Camera ***) - click on the "***",

3 - There are now two rows in the Toolbad. Click on "More".

4 - Click on "Syntax highlighter".

> And the m_byInterruptLevel and m_byInterruptPriority are for every EPORT the same but for Port to Port different.

They MUST be different for every separate interrupt source, and that includes every EPORT. All seven of them have to unique Priority:Level. So if you want all EPORTs at the the same level, then they have to have priorities 1, 2, 3, 4, 5, 6, 7.

13.2.1.6 Interrupt Control Register (ICRnx, (x = 1, 2,..., 63))

Note: It is the responsibility of the software to program the ICRnx
registers with unique and non-overlapping level and priority definitions.
Failure to program the ICRnx registers in this manner can result in
undefined behavior. If a specific interrupt request is completely unused,
the ICRnx value can remain in its reset (and disabled) state.
Figure 13-9. Interrupt Control Register (ICRnx)

Everyone thinks on reading that that you can only have 64 different interrupts active in a system. But you shouldn't be using Level 7, so there are only 8 priorities and 7 levels, so that means only 56 interrupts. It is very easy to run out, as there are 60 interrupts on INTC0, and 51 on INTC1.

Except (and it doesn't say this anywhere) the interrupts only have to be unique within one controller. So you can use (say) Level 4 and Priority 4 for an interrupt on INTC0 and use the same Level and Priority for a different interrupt on INTC1.

I suggest you search this Forum for "It is the responsibility of the software to program the ICRnx" and look at previous interrupt controller problems and answers.

The above probably isn't causing this problem.

You're not writing to "EPFn" anywhere that I can see. You should do that before enabling interrupts (to clear any previous ones). That wouldn't cause your problem either.

// Clear Interrupt Mask Bits
          MCF_INTC0_IMRL &= ~MCF_INTC0_IMRL_MASKALL;                    // bit 0 = mask All bit =>UnMask
          MCF_INTC0_IMRL &= ~MCF_INTC0_IMRL_INT_MASK(m_byPortNr);     // UnMask Bit m_byPortNr = EPORTx

I thought the above might be a problem, but it is OK. You're clearing the MASKALL bit, and then that allows the other ones to be cleared. Check that second macro is doing what you expect. Also note that the fact that EPORTs 1-7 use INTC0 Interrupts 1-7 is a fluke. That doesn't work anywhere else. So the "type" of "m_byPortNr" isn't the same as the argument to that macro, but it works. It would be slightly cleaner (for other code) to make this mapping more explicit somewhere.

Back to your original problem. Assuming you can duplicate it (enable one port interrupt, enable a second, disable the first and the second one now doesn't work) I'd suggest you:

1 - Write some code to dump all the EPORT and relevant INTC0 registers.

2 - Dump the registers.

3 - Enable two EPORTs.

4 - Dump the registers.

5 - Disable one EPORT (causing the other one to stop).

6 - Dump the registers.

7 - Compare the last two dumps for all differences. Look for anything that explains the port that doesn't work.

Tom

0 Kudos

953 Views
TomE
Specialist II

Are you sure you have unique levels and priorities for all the separate interrupts in the ICRs? That can cause problem if you don't have them all unique.

13.2.1.6 Interrupt Control Register (ICRnx, (x = 1, 2,..., 63))

Tom

0 Kudos

953 Views
richardwielend
Contributor I

Thank you very much for the help!!

I have not found the "Syntax highlighter" button...

EPORT.cpp

void
EPORT::InterruptOn()
/*-FUNCTION HEADER--------------------------------------------------------
|   description  : enables a certain interrupt
|   side effects :
|   parameters   :
|   return value : none
|   precondition :
|   postcondition:
+--END FUNCTION HEADER--------------------------------------------------*/
{
     mcf523x_irq_disable();     
     MCF_EPORT_EPIER |= MCF_EPORT_EPIER_EPIEx(m_byPortNr);
     mcf523x_irq_enable();     
}
void
EPORT::InterruptOff()
/*-FUNCTION HEADER--------------------------------------------------------
|   description  : disables a certain interrupt
|   side effects :
|   parameters   :
|   return value : none
|   precondition :
|   postcondition:
+--END FUNCTION HEADER--------------------------------------------------*/
{
     mcf523x_irq_disable();     
     MCF_EPORT_EPIER &= ~MCF_EPORT_EPIER_EPIEx(m_byPortNr);
     mcf523x_irq_enable();     
}

mcf523x_eport.h:

#define MCF_EPORT_EPIER    (*(vuint8 *)(void*)(&__IPSBAR[0x130003]))
#define MCF_EPORT_EPIER_EPIEx(x)         (0x01)<<(x)

m_byPortNr is the member variable of the EPORT defining the port and yes it´s 1-7.

asm int asm_set_ipl(UINT32)
{
     
     link     a6,#-8
     movem.l     d6-d7,(sp)

     move.w     sr,d7          /* current sr      */

     move.l     d7,d0          /* prepare return value      */
     andi.l     #0x0700,d0     /* mask out IPL      */
     lsr.l     #8,d0          /* IPL      */

     move.l     8(a6),d6     /* get argument      */
     andi.l     #0x07,d6          /* least significant three bits      */
     lsl.l     #8,d6          /* move over to make mask      */

     andi.l     #0x0000F8FF,d7     /* zero out current IPL      */
     or.l     d6,d7               /* place new IPL in sr      */
     move.w     d7,sr

     movem.l     (sp),d6-d7
     lea          8(sp),sp
     unlk     a6
     rts
}
/********************************************************************/
void
mcf523x_irq_enable(void)
{
     asm_set_ipl(0);
}
/********************************************************************/
void
mcf523x_irq_disable(void)
{
     asm_set_ipl(6);
}

Adding the disabling and enabling didn´t made a difference.

0 Kudos

953 Views
TomE
Specialist II

> Do you have an idea what I´m doing wrong?

I can't read the scrambled mess you've pasted in. Try reformatting it so it can be read.

Hint - click on "use advanced editor" and then click on the "dots" to get the "Expanded Toolbar".

Then click on the "More" and "Syntax Highlighter" and then paste your code in THERE with an appropriate "Language".

They really couldn't have hidden this much deeper. If I wanted to navigate a "maze of twisty little passages" to find hidden treasures, I'd play Zork.


Other sites I use have an "Insert Code" BUTTON on the main toolbar, as that's what we're wanting to do most of the time.

I've just noticed a "<>" on the Advanced Toolbar which is called "Source Code". I thought that might be for pasting "Source Code" in, but it shows the HTML "source code" of this page itself, in case you want to try and write raw HTML to bypass the interface they've given you.

You also need to provide some sort of reference as to where the "MCF_EPORT_EPIER" and "MCF_EPORT_EPIER_EPIEx()" definitions come from, preferably links where we can read the header files that define these. Given they're probably CW and not on the internet, you should paste parts of the defining headers in so we can see what those macros actually do.

What actual values are you passing in as "m_byPortNr"? Valid values are probably "1" to "7".

It would also be worth disassembling your code and see what assembly instructions it is actually turning into. That might give a hint as to the problem.

You should also disable interrupts around these operations or you'll risk getting Spurious Interrupts.

Tom

0 Kudos