Match Control Register Interrupt Event Handler

After reading the LPC23XX User manual and playing around with the register class, Im able to raise an interrupt (MR3 Interrupt) from the Match Control Register on a given timer on my Panda! Now comes the part where Im lost. How can I create an event handler for this interrupt?

Is it possible to associate this Interrupt to an interruptible pin, where I can add an event handler? Or, is there a way to construct an event handler for any given interrupt?

You need to do it in RLP.

Gus,

Thanks for the quick response. I was hoping for a different answer, Ive been deeding diving into the RLP stuff. Im sure youre already aware of my next question!!! Do you know of an example that I could use to help get me started on this (interrupts, that is)? Ive spent a great deal of time this weekend reading about RLP, and, well, I dont feel like gotten anywhere.

Oh, a word to the wise. I moved my timer/counter code over to the mini this weekend and found that Cap2.0 and Cap2.1 (pins 80 and 81) are not mapped. Thankfully, Cap3.0 is available through An0 (pin 9), so timer three works just fine!

I guess I should discuss my project briefly. Im in process of building a single axis modular motion control solution using the mini. The idea is to be able to drive a stepper, RC servo, or bushed DC motor with full encoder feedback (in the XX KHz range). Im using a Toshiba TB6560AHQ as the Stepper driver, which has a 3.5amp limit for around $5.00!

This project is still in its infancy, but its coming together nicely!

If I could beg, borrow, or steal enough help to get this RLP interrupt working on the match control register, I would gladly post this project on the code site. This bone really isnt a very good one, since I was planning to post the project anyway! But all the same, any help here would be greatly appreciated!

You will always get help here, from GHI and from community :slight_smile:

The problem is that you are doing something way too advanced, not only using RLP, you need to hook into the interrupt controller as well. I do not recall if RLP has extension s to help you with interrupt controller. I do not know how experienced you are but you really need ot know plenty in order for you to get into native interrupts.

If you are doing this for fun, and it looks like it, then do it the fun and easy way. Try to find a way to get what you need without digging into native interrupt handlers.

Lets start with this, why do you need match register? Is there a little chip that can do what you need then control that chip from NETMF?

For my experience, it is certainly outshined by my enthusiasm. I dont have a great deal of experience, but Im generally tenacious enough to get things working. Generally, is the key word here!

My original goal is to provide an interrupt at ramp end, decel start, and stop on my motion profile. After reading about the match control register, this seemed like a great fit. That is, other than triggering an event based on the interrupts associated with the MCR. Im sure I could construct a hardware system to control externally, but a couple of my colleagues have egged me on that this is certainly possible with ST32 or Arduino (havent checked on this just yet). Egos aside, this has now become a matter of principle! Joking aside, Im not ready to give up on this line of thought just yet. Ill continue to study this, and if you have any thoughts, Im sure they will be useful. Thanks for you help!

Just a thought, but Im wondering if I could simply toggle (logic high or low) an interruptible pin from RLP, and capture that in the C# application as a native FEZ_Pin (say Di4) with an added event handler?

And it is certainly possible on a raw LPC chip used on your FEZ. That is programming it in C (RLP), the same way you would on other micros. The point here is being able to use a modern programming environment (NETMF) to fill your high end needs need. You need to use the right tool for the right job.

We will be here when you need more help :slight_smile:

Well, some people just dont know when to give up!

The key is to open MAT3.0 on P0.10. Then use the External Match Register to set this pin logical high or low on match/interrupt. P0.10 is mapped to Di8 on the Mini, so I was able to create an Interruptible pin and an event handler for Di8.

You were right about using the right tool for the job, and FEZ continues to be that tool for me!

Heres my test code


/*
 * This code demonstrate how to use timer3 on the FEZ Mini to create an externally 
 * triggered high speed counter with interrupt and event handling.  
 * 
 * See: http://www.keil.com/dd/docs/datashts/philips/lpc23xx_um.pdf
 * See: http://www.ghielectronics.com/downloads/FEZ/Mini/FEZMini_sch.pdf
 * 
 */

using System;
using System.Threading;

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

using GHIElectronics.NETMF.FEZ;

using GHIElectronics.NETMF.Hardware.LowLevel;
using GHIElectronics.NETMF.Hardware;

namespace FEZ_Mini_Counter
{
    public class Program
    {
        private static Register T3CR;   //Timer Control Register
        private static Register T3IR;   //Interrupt Register 

        static void IntButton_OnInterrupt(uint port, uint state, DateTime time)
        {
            //reset
            T3CR.SetBits((1 << 1));
            T3CR.ClearBits((1 << 1));
            T3IR.Write(1 << 0);
        }

        static void IntDI8_OnInterrupt(uint port, uint state, DateTime time)
        {
            //The external match register caused an interrupt
            Debug.Print("INTDI8 Interrupted");
        }

        public static void Main()
        {
            //Disable the garbage collector messages
            Debug.EnableGCMessages(false);

            //used to generate our external timer input, could be an encoder.
            PWM pwm = new PWM((PWM.Pin)FEZ_Pin.PWM.Di3);
            pwm.Set(false);
            pwm.Set(2, 50);


            //The LDR button is used as a physical counter and interupt reset
            InterruptPort IntButton = new InterruptPort((Cpu.Pin)FEZ_Pin.Interrupt.LDR, true,
                                   Port.ResistorMode.PullUp,
                                   Port.InterruptMode.InterruptEdgeBoth);
            IntButton.OnInterrupt += new NativeEventHandler(IntButton_OnInterrupt);


            //DI8 is used as the MAT3.0 pin, interrupted by the External Match Register
            InterruptPort IntDI8 = new InterruptPort((Cpu.Pin)FEZ_Pin.Interrupt.Di8, true,
                                   Port.ResistorMode.PullUp,
                                   Port.InterruptMode.InterruptEdgeBoth);
            IntDI8.OnInterrupt += new NativeEventHandler(IntDI8_OnInterrupt);


            /*PINSEL0 - 0xE002 C000
             * 21:20 P0.10 GPIO Port 0.10 TXD2 SDA2 MAT3.0 00
             * see page 157, LPC23XX User manual Rev. 02 — 11 February 2009
             * 
             * Use the Pin function select register PINSEL0, to enable MAT3.0
             * on P0.10.  This is used for the External Match Register
            */
            Register PINSEL0 = new Register(0xE002C000);
            PINSEL0.Write(3 << 20);

            /*Power Control for Peripherals register (PCONP - 0xE01F C0C4)
             * 23 PCTIM3 Timer 3 power/clock control bit.
             * see pages 68-69, LPC23XX User manual Rev. 02 — 11 February 2009
             * 
             * In the Power Control for Peripherals register, turn on bit 23
             * to turn power on for timer3
             */
            Register PCONP = new Register(0xE01FC0C4);
            PCONP.SetBits(1 << 23);

            /*Pin Function Select Register 1 (PINSEL1 - 0xE002 C004)
             * 15:14 P0.23 GPIO Port 0.23 AD0.0 I2SRX_CLK CAP3.0 00
             * see page 158, LPC23XX User manual Rev. 02 — 11 February 2009
             * 
             * Use the Pin finction select register PINSEL1, to enable Cap3.0
             * on P0.23.  Select An0 on Mini (Cap3.0) - An0 - Mapped to the Cap3.0
             * This will be the external input for the timer, used with the Capture Control Register
             */
            Register PINSEL1 = new Register(0xE002C004);
            PINSEL1.SetBits((3 << 14));//set bits 14 and 15

            /*Timer Control Register (T[0/1/2/3]CR - 0xE000 4004, 0xE000 8004,0xE007 0004, 0xE007 4004)
             * 0 Counter Enable When one, the Timer Counter and Prescale Counter are enabled for counting. 
             * When zero, the counters are disabled
             * see pages 554-555, LPC23XX User manual Rev. 02 — 11 February 2009
             * 
             * This will enable timer3
             */
            T3CR = new Register(0xE0074004);
            T3CR.Write(1);

            /*TPrescale register (T0PR - T3PR, 0xE000 400C, 0xE000 800C, 0xE007 000C, 0xE007 400C)
             * The 32-bit Prescale register specifies the maximum value for the Prescale Counter.
             * see page 556, LPC23XX User manual Rev. 02 — 11 February 2009
             * 
             * This will set the prescale to 0 for timer3
             */
            Register T3PR = new Register(0xE007400C);
            T3PR.Write(0);

            /*Count Control Register (T[0/1/2/3]CTCR - 0xE000 4070, 0xE000 8070, 0xE007 0070, 0xE007 4070)
             * 10 Counter Mode: TC is incremented on falling edges on the CAP input selected by bits 3:2.
             * see page 555, LPC23XX User manual Rev. 02 — 11 February 2009
             * 
             * This will count on falling edge of CAP3.0, An0(mini)
             */
            Register T3CTCR = new Register(0xE0074070);
            T3CTCR.Write(2 << 0 | 0 << 2);

            /*Capture Control Register (T[0/1/2/3]CCR - 0xE000 4028, 0xE000 8028, 0xE007 0028, 0xE007 4028)
             * see page 558, LPC23XX User manual Rev. 02 — 11 February 2009
             * 
             * This is set to 0, for a counter
             */
            Register T3CCR = new Register(0xE0074028);
            T3CCR.ClearBits(0x07);
            // To reset the counter
            T3CR.SetBits((1 << 1));
            T3CR.ClearBits((1 << 1));

            /*------------------------------------------------------------------*/

            /*Match Control Register (T[0/1/2/3]MCR - 0xE000 4014, 0xE000 8014, 0xE007 0014, 0xE007 4014)
             * 0 MR0I 1 Interrupt on MR0: an interrupt is generated when MR0 matches the value in the TC
             * see page 557, LPC23XX User manual Rev. 02 — 11 February 2009
             * 
             * This will generate a interrupt when MR0 and TC match
             */
            Register T3MCR = new Register(0xE0074014);
            T3MCR.Write(1 << 0);

            /*MR0 Match Register
             * see page 553, LPC23XX User manual Rev. 02 — 11 February 2009
             * 
             * This is value that will be tested against the TC
             */
            Register T3MR0 = new Register(0xE0074018);
            T3MR0.Write(10); // change this value as needed

            /*Interrupt Register (T[0/1/2/3]IR - 0xE000 4000, 0xE000 8000, 0xE007 0000, 0xE007 4000)
             * MR0 Interrupt Interrupt flag for match channel 0.
            * see page 554, LPC23XX User manual Rev. 02 — 11 February 2009
            * 
            * This provides the interrupt on MR0
            */
            T3IR = new Register(0xE0074000);
            T3IR.Write(1 << 0);

            /*External Match Register (T[0/1/2/3]EMR - 0xE000 403C, 0xE000 803C, 0xE007 003C, 0xE007 403C)
             * see page 559, LPC23XX User manual Rev. 02 — 11 February 2009
             * 
             * Handel the interrupt on EM0 (MAT3.0)
             * Setting bits 5:4 high, toggles the corresponding External Match bit/output (MAT3.0).
             */
            Register EM0 = new Register(0xE007403C);
            EM0.Write(3 << 4);

            /*Timer Counter registers (T0TC - T3TC, 0xE000 4008, 0xE000 8008, 0xE007 0008, 0xE007 4008)
             * see page 556, LPC23XX User manual Rev. 02 — 11 February 2009
             * 
             * This is the count of Timer3
             */
            Register T3TC = new Register(0xE0074008);

            while (true)
            {
                Debug.Print("Total count: " + T3TC.Read());
                Debug.Print("IR: " + T3IR.Read());
                Debug.Print("External Match Register: " + EM0.Read().ToString());

                Thread.Sleep(10);
            }//end of while loop

        }//end of Main()

    }//end of class
}//end of namespace


1 Like

We have a new expert in the house :slight_smile:

Can you document this on code.tinyclr.com please?

This has been added to the code.tinyclr.com site!

http://code.tinyclr.com/project/360/externally-triggered-high-speed-counter/

and with video too, very nice of you. Thanks for sharing.

Hi Jareds,

This is exactly what I need to do myself, unfortunately, the link in your post does not seem to work. Could you possibly let me know where I can view this code?

Thanks
Shawn

http://www.tinyclr.com/codeshare/entry/298

Enjoy.

Great!

Thanks alot.