chipKIT® Development Platform

Inspired by Arduino™

Help on nesting interrupts (nesting is not a crime!)

Created Sun, 25 Nov 2012 10:24:06 +0000 by iamnotachoice


iamnotachoice

Sun, 25 Nov 2012 10:24:06 +0000

Hey chipKitters (and chipKittens)!

Since I usually only use timers in the most simple way (for timing) I ran into a timer interrupt problem here where I need the help of some pros here, I would be glad if someone knows the answer! Thanks already!

My code runs two timer services: The first one is superslim and called very often. The second timer service is called not so often, but it involves some math for the reason described below. I am trying to make the first timer service interrupt the second one! Until now, no success. I tried interrupts() in the first line of the slower timer callback to reenable the interrupts with no effect.

If nesting interrupts is simply not possible, that would be, of course, also an answer to my problem ;), I was hoping that nesting would be no problem as long as both services together don't take more time than I make available with the given timing in the callback return.

Thanks for your advice, Moritz

PS: For the why: The faster timer generates pulses for a stepper motor driver, the slower timer calculates speed and acceleration of the steppers moving. I put those heavy calculations into a timer, because it relives me of the nessesity to measure the time between two calls, that I need for the speed calculations, since i know the time that has passed by. My alternative code is measuring the micros(), dealing with the zero-overflow of the long micros() returns, and then returning the measured interval time. Also nice, but in my opinion, a timer is just more elegant for that, what do you think?


EmbeddedMan

Sun, 25 Nov 2012 17:47:08 +0000

From a hardware perspective, there's no reason you can't nest interrupts. There are 7 interrupt levels, so if you give each of your ISRs a different level, you should have no problem. Read the PIC32 Family Reference Guide chapter 8 (Interrupts) [url]http://ww1.microchip.com/downloads/en/DeviceDoc/61108G.pdf[/url] to get a better grasp on how interrupts are handled and how you can turn on nesting.

However, I'm not convinced that your architecture is the best one. I have code doing exactly what yours is (from a high level) where I have a 300Khz timer based interrupt that's doing the step and direction generation for 2 stepper motors. But I don't use an interrupt for the math part. Instead, I have a simple FIFO move list, and the ISR pulls move data from that FIFO as it needs it. The main line code feeds the FIFO (i.e. does the math to generate the move data). Whenever there is space in the FIFO, the main line code computes another line segment worth of data and puts it in the FIFO. This allows the main line code to do other things too, but still never let the ISR run dry.

I'm not saying the above is the best way, it's just different, and has some advantages.

*Brian


iamnotachoice

Sun, 25 Nov 2012 19:11:01 +0000

Hi!

Thank you very much for the input. The FIFO-way probably has the smarter pipeline, but I mean we have a very fast cpu here, we can compute jitter-free pulses for high-res microsteps in realtime (if I knew how to use timers properly.. hehe..).

Digging into that, I understand that there are levels and (shadow) registers. Can you give me another hint how I can assign a level to my timer? I am currently using:

attachCoreTimerService(heavyMathCallback);
attachCoreTimerService(slimStepCallback);

to attach my callbacks to the timer services which look like:

uint32_t heavyMathCallback(uint32_t _now){
  //..heavy..math..with..squareroots..
  return _now+ROUND_ABOUT_100_MICROS;
}
uint32_t slimStepCallback(uint32_t _now){
  //..triggering..pulses..
  return _now+ROUND_ABOUT_20_MICROS;
}

..where I have to say that the slimStepCallback() will begin the pulse for the adressed motors in one round and ends the pulse when it is called in the next round.

Thanks a lot, Regards, Moritz


EmbeddedMan

Mon, 26 Nov 2012 03:41:18 +0000

I don't have any specific code off the top of my head, but you won't find this type of stuff in the MPIDE/Arduino abstraction layer. You will either need to write to the registers directly (look up in the PIC32 Reference Manual for that information) or use the Microchip supplied PLIB library which has some nice function calls for accessing all PIC32 registers. You can download the free version of XC32 and then look at the documentation files installed with that for more information on PLIB.

*Brian


iamnotachoice

Wed, 28 Nov 2012 08:24:47 +0000

Hey!

Thank you a lot Brian, this library is just the hint I needed!

CYA, Moritz