Created Sun, 06 Jul 2014 22:40:32 +0000 by w5uxh
Sun, 06 Jul 2014 22:40:32 +0000
Not sure where to post this query, so will try here.
I am just starting with MPIDE (now moved to UECIDE though) trying to learn how to control interrupts in the MAX32. I managed to find examples for the timers and have the setup function and interrupt handler working, including the clear interrupt macro for the timer in use.
I now need to get external interrupts working. I think I will be able to use attachInterrupt, but had to dig to try to find the correct macro to clear the interrupt bit in the handler. I think I probably have found the macro for INT2: mINT2ClearIntFlag. Assuming I have this right, I found it in each of the "legacy" headers listed here:
hdwr-pic32-compiler-pic32Tools-pic32mx-include/peripheral/legacy/int_1xx_2xx_legacy.h hdwr-pic32-compiler-pic32Tools-pic32mx-include/peripheral/legacy/int_3xx_4xx_legacy.h hdwr-pic32-compiler-pic32Tools-pic32mx-include/peripheral/legacy/int_5xx_6xx_7xx_legacy.h
I have not figured out what the 1xx, 2xx, etc. are, perhaps related to processor families? The definition of the macro seems to be identical in the several header files I looked at.
I wonder if there is some useful documentation for finding things like this or is it a matter of google searches for examples and a lot of grep usage in the libraries and headers folders?
Thanks,
Chuck
Sun, 06 Jul 2014 22:58:56 +0000
At one point I went through and tried to find everything I could on interrupts and put it here:
http://globedrop.com/wiki/user:jacob#chipkit_pic32_interrupt_treaties
I don't think it has what your looking for though.
I also agree that the 1xx, 2xx ect probably refer to chip families.
Jacob
Sun, 06 Jul 2014 23:14:49 +0000
The chipKIT core has its own internal system for handling interrupts. You shouldn't be manually configuring interrupts.
The best reference really for learning how the chipKIT core does it is to look at the SoftServoPWM library source code. There are specific functions you should call to attach the interupt, set its priority, enable it, etc.
And yes, the 1xx, 2xx etc refer to the chip families (eg pic32mx250f128d is a 2xx chip, the pic32mx795f512l is a 7xx chip).
Mon, 07 Jul 2014 01:08:21 +0000
Thanks Jacob and Majenko,
I guess I am too confused at this point. First, in SoftServoPWM, I see where interrupts are attached to the core timer, but my understanding is that there can be up to 1 msec "jitter" in the response to the core timer interrupt which is too much for my application.
For my timer interrupt, I used this code to set up an interrupt for a 32 bit timer:
OpenTimer23(T23_ON | T23_PS_1_1 | T23_SOURCE_INT, pdlDotLength_12_5nsec);
ConfigIntTimer23(T23_INT_ON | T23_INT_PRIOR_2);
INTEnableSystemMultiVectoredInt();
(I copied the INTEnable line from an example, no idea if it is needed, have not tested without it yet.)
and this for the handler (just wanting to verify operation and timing with the scope):
extern "C" {
static int x = 0;
void __ISR(_TIMER_23_VECTOR, ipl2) _Timer23Handler(void) {
digitalWrite(PIN_LED1, x & 0x01);
x++;
mT23ClearIntFlag();
}
}
where I thought I needed the mT23ClearIntFlag() function to clear the flag before exiting the handler.
I thought I would need something similar for setting up an external interrupt handler, where I would use attachInterrupt to attach a handler to the interrupt for an external input and thought I would need a clear interrupt operation for this handler also.
I had found the example code from GeneApperson using attachInterrupt:
attachInterrupt(intTest, IsrTest, RISING);
which seemed straight forward. He also had code for the handler:
IsrTest() {
intStat = 1 - intStat;
if (intStat != 0) {
digitalWrite(pinLED2, HIGH);
}
else {
digitalWrite(pinLED2, LOW);
}
which confuses me because there does not seem to be a clear interrupt operation. I then found the mINT2ClearIntFlag macro and thought it probably would be needed. I have not tried to test the external interrupt yet, just made my best guesses at how it should go.
But if I should be using completely different methods for setting up a Timer23 interrupt and an external INT2 interrupt, I suppose I am really lost.
I will print out the SoftServoPWM files tomorrow and see if I can see how examples in that library relate to what I need.
Thanks again, Chuck
Mon, 07 Jul 2014 01:20:05 +0000
There's far, far less than 1ms of jitter on the Core Timer. If there was, how could I run 84 simultaneous RC servos? They'd be going crazy all over the place rather than doing what I had programmed them.
The jitter on the CoreTimer can get larger the more pieces of code hook into it. But with just one (like SoftPWMServo) the jitter is amazingly low - like sub 1uS most of the time I think.
*Brian
Mon, 07 Jul 2014 03:59:44 +0000
I probably was not understanding the information below the first time I read it and the "within 1 msec" is what I had in my head. I will need to eventually understand what this means:
[color=#4040FF]When a core timer service function is registered, the first call to the function will occur on the next regularly scheduled call to the CoreTimerHandler ISR. The system always has a millisecond CoreTimer Service registered [/color] [color=#FF0000]and this will typically ensure that a newly registered Service will be called within 1 ms of being registered. [/color]
So if I want to switch an output pin to logic 1 and register a core timer service to interrupt me 10 msecs later so I can switch the pin back to logic 0, the timing will be accurate within a few usecs or less? I will play with this service for my next test.
Mon, 07 Jul 2014 04:21:15 +0000
That information is confusing. What it means is that, the first time you register your new CoreTimer function, it will be called within about 1ms of when you want it to be called.
However, every time after that, it will be far more accurately scheduled then that. Like sub 1uS.
The reason it works this way was a design tradeoff. We could have made the first call of your function at the higher accuracy, but it would have complicated the CoreTimer code a lot more, and the tradeoff seemed worth it.
*Brian
Mon, 07 Jul 2014 09:32:27 +0000
For external interrupts you use attachInterrupt(). You do not need to clear the interrupt flag - that is done for you. Your code is not an interrupt handler, but is called by a pre-written interrupt handler.
For working with other interrupts you should not be using any of the peripheral library functions. They confuse the internal interrupt table system. Instead the functions you should be using are:
isrFunc setIntVector(int vec, isrFunc func)
isrFunc getIntVector(int vec)
isrFunc clearIntVector(int vec)
uint32_t getIntFlag(int irq)
void clearIntFlag(int irq)
uint32_t setIntEnable(int irq)
uint32_t clearIntEnable(int irq)
void restoreIntEnable(int irq, uint32_t st)
void setIntPriority(int vec, int ipl, int spl)
void getIntPriority(int vec, int * pipl, int * pspl)
The code for all those is in WSystem.c in the chipKIT core.
You do not need to enable multi-vector interrupts. All that is already taken care of. You just need to attach your ISR function (as a normal function) with setIntVector(), set the priority with setIntPriority(), and enable it with setIntEnable(). Then in your interrupt function you can check getIntFlag() to test the IF flag, and call clearIntFlag() to clear it.
With that there is no need to place any ISR functions in a C namespace, no need to flag them as interrupts, nothing. They are just normal run-of-the-mill functions.
Oh, and the "isrFunc" type is:
typedef void (*isrFunc)(void);
so your functions should just be:
void myIsrFunc() {
// ...
};
Mon, 07 Jul 2014 11:52:16 +0000
Majkento: your information looks like exactly what I needed. I want to use the proper procedures but have not been able to find a guide of any sort (probably right under my nose somewhere out there) I think this will be a big help.
Brian: thanks for the explanation of the core timer comments.
Chuck