MOD54415 HiRes Timer vs Watchdog
-
- Posts: 192
- Joined: Mon Dec 17, 2012 6:24 am
MOD54415 HiRes Timer vs Watchdog
Hi all,
I'm trying to implement a timer based interrupt routine into my code. I need the timer to run in the background and not delay the program. I'm not sure f I should use the HiRes timer or the Watchdog timer for this - The HiRes timer seems to suggest that it will delay the program when called instead of running in the background... Can someone clarify this? Thanks!!
I'm trying to implement a timer based interrupt routine into my code. I need the timer to run in the background and not delay the program. I'm not sure f I should use the HiRes timer or the Watchdog timer for this - The HiRes timer seems to suggest that it will delay the program when called instead of running in the background... Can someone clarify this? Thanks!!
-
- Posts: 513
- Joined: Sat Apr 26, 2008 7:14 am
Re: MOD54415 HiRes Timer vs Watchdog
The Hi Res timer can certainly work in background/IRQ mode although it can also be configured to poll a delay.
However, for many timer based apps, particularly repeat events at a fixed mSec to second interval, it may be overkill.
I'd look at the PIT timer. One-time usec delays are easy, but if they are regular, things will bog down.
Can't remember of the top of my head, but I think the PIT is 16 bit resolution, while the "Hi-res" uses the DMA timer module which is 32 bit resolution.
Also remember that the OSTime delay tick uses PIT ch 0, and debugger uses ch 3 I'm pretty sure.
See:
C:\nburn\examples\MOD5441X\PIT-Timer\main.cpp and in particular the built in function InitPitOSSem() which posts a semaphore in every PIT ISR.
See: C:\nburn\MOD5441X\system\pitr_sem.cpp and C:\nburn\MOD5441X\include\pitr_sem.h
For background on the PIT module, see the appnote on the PIT for the MOD5270: http://www.netburner.com/support/docume ... mer-2/file which can be ported to the 54415 fairly easily.
However, for many timer based apps, particularly repeat events at a fixed mSec to second interval, it may be overkill.
I'd look at the PIT timer. One-time usec delays are easy, but if they are regular, things will bog down.
Can't remember of the top of my head, but I think the PIT is 16 bit resolution, while the "Hi-res" uses the DMA timer module which is 32 bit resolution.
Also remember that the OSTime delay tick uses PIT ch 0, and debugger uses ch 3 I'm pretty sure.
See:
C:\nburn\examples\MOD5441X\PIT-Timer\main.cpp and in particular the built in function InitPitOSSem() which posts a semaphore in every PIT ISR.
See: C:\nburn\MOD5441X\system\pitr_sem.cpp and C:\nburn\MOD5441X\include\pitr_sem.h
For background on the PIT module, see the appnote on the PIT for the MOD5270: http://www.netburner.com/support/docume ... mer-2/file which can be ported to the 54415 fairly easily.
-
- Posts: 192
- Joined: Mon Dec 17, 2012 6:24 am
Re: MOD54415 HiRes Timer vs Watchdog
Aaah, thanks Ridgeglider, that's some useful info!! I need a consistent timer that will interrupt at 1 second intervals, one that will interrupt at 0.2 seconds, and one that interrupts at 0.1 second intervals - always gets restarted and only one is running at a time... Sounds like the HiRes timer is the one I need. The ISR doesn't do anything too fancy - just read a MUX and ADC, send a UDP packet, and restart itself. That's all. I would assume that I could set up one timer to do all that, and just change the timer value at whatever point I need?
Re: MOD54415 HiRes Timer vs Watchdog
That you can. Though, do note that there is a setup time for defining a new delay time/frequency of tens of microseconds. If you need tighter timing, you can either a) learn the hardware and implement your timing directly and simply store the values, or b) setup multiple timers and just start/stop them as needed.
Dan Ciliske
Project Engineer
Netburner, Inc
Project Engineer
Netburner, Inc
-
- Posts: 513
- Joined: Sat Apr 26, 2008 7:14 am
Re: MOD54415 HiRes Timer vs Watchdog
Not to plug the PIT too hard, take a look at the PIT example C:\nburn\examples\MOD5441X\PIT-Timer and the 1 sec code is already set up to post a semaphore from an ISR to a pending task for you! Instead of doing the MUX, ADC, and UDP start from within an ISR, consider doing it in a task that pends on the semaphore. The switch from ISR to task is about 6 uSec (Dan?). To change the period, simply disable the PIT ISR, set a state variable to indicate MUX/ADC/UDP, then recall the InitPitOSSem() function. Your task would check the state and act on the MUX, ADC, or UDP job accordingly. I think the PIT may have lower overhead than the HiRes and although you do need another task it should probably use less stack space than a default task stack.
-
- Posts: 192
- Joined: Mon Dec 17, 2012 6:24 am
Re: MOD54415 HiRes Timer vs Watchdog
Thanks Dan, I did use 3 separate timers. As the system reaches it's critical points it will switch timers correctly - I've proved that out. But I did hit a snag with them...
Also, Thanks RidgeGlider, it sounds awesome, but I'm gonna confess, I know far too little about semaphores and how they work. I tried using them once or twice and if I follow a code example, I'm fine but truly understanding them is where I falter and being able to use them properly will take some figuring out in my abundant spare time... But for you and Dan to consider, here's what I've done so far:
This code executes in my UserMain() loop immediately before the main while() loop:
followed by the CWT set up for 1.07 second intervals:
My ISR routines call the ADC and MUX functions form their class BUT... the software now freezes as soon as the DSPIStart() function is called. I saw this initially when CWT kept rebooting the system. Once disabed, and with a little debug work, I saw the system freeze up each time when stepping into that function. Disabling the HIRes Timer (using only one to start) allowed everything to work again. Is there a specific reason this would happen? The SPI channels are running at 10MHz and 16MHz (MUX and ADC respectively) so I can't see why the SPI function would freeze - the process is really fast... Any ideas?
MUX Code:
RidgeGlider, I'll try messing with semaphores over the weekend and see if I can wrap my brain around them. I'm not new to C and C++ anymore, but I'm still a bit of a newb, not that it's an excuse. But I'm willing to investigate since you are proposing a great alternative. But I would appreciate your input on the error if you could be so kind. Thanks!!
Also, Thanks RidgeGlider, it sounds awesome, but I'm gonna confess, I know far too little about semaphores and how they work. I tried using them once or twice and if I follow a code example, I'm fine but truly understanding them is where I falter and being able to use them properly will take some figuring out in my abundant spare time... But for you and Dan to consider, here's what I've done so far:
This code executes in my UserMain() loop immediately before the main while() loop:
Code: Select all
timer0 = HiResTimer::getHiResTimer(0); // initialize HiRes timer0
timer1 = HiResTimer::getHiResTimer(0); // initialize HiRes timer1
timer2 = HiResTimer::getHiResTimer(0); // initialize HiRes timer2
timer0->setInterruptFunction(timer_ISR); // Point timer interrupt call-back to timer_ISR()
timer1->setInterruptFunction(timer_ISR); // Point timer interrupt call-back to timer_ISR()
timer2->setInterruptFunction(timer_ISR); // Point timer interrupt call-back to timer_ISR()
timer0->init(0.95); // initial start of timer is ~1 second per data poll - <1sec to ensure CWT reset.
timer1->init(0.2); // initial start of timer is 1/5th second per data poll.
timer2->init(0.1); // initial start of timer is 1/10th second per data poll.
timer0->start(); // start timer0 for 1x per second poll
Code: Select all
unsigned short settings = 0; // simple masking variable for CWCR
settings |= 0x8000; // sets CWCR as read-only - bit 15
settings |= 0x001B; // sets timeout to 1.07 seconds - bits 4-0
settings |= 0x00C0; // bit 7 = enable, bits 6-5 = generate system reset on timeout
sim2.scm.cwcr = settings; // load CWCR - starts WDT immediately
MUX Code:
Code: Select all
void funcs::MUX_Read() // reads mux inputs and returns them to caller
{
WORD MUX_OUT[32];
BYTE MUX_Tx[3], MUX_Rx[3]; // MUX TX Buffer. Not receiving data from the mux so MUX_Rx might not be used...
MUX_Tx[0] = 0x40; // sends address and r/w code to gpio expander - 0b01000000
MUX_Tx[1] = 0x0A; // loads register address code to set output latch - OLAT
if (enabled)
{
// poll all mux positions - inputs listed as s1-s32, but coded from 0 to 31
for (BYTE i = 0; i < 32; i ++)
{
J2[33] = 0; // enable IO
MUX_Tx[2] = i; // writes the incremented position to OLAT of the 8b breakout
J1[5] = 0; // MUX CS line drop
J1[6] = 0; // MUX WR line drop
J1[7] = 1; // MUX EN line high
DSPIStart(1, MUX_Tx, MUX_Rx, 3, NULL, true); // Data to GPIO breakout to switch mux
while(!DSPIdone(1)); // release when done
if (J2[32])
{
MUX_OUT[i] = MYSYS_FAULT_FOUND; // loads a "pin on" value (chosen so as not to be 1 or 0)
faultset(MYSYS_MUX[i], true); // sets specific fault
}
else
{
MUX_OUT[i] = MYSYS_NO_FAULT; // loads a "pin off" value (chosen so as not to be a 1 or 0)
faultset(MYSYS_MUX[i], false); // clears specific fault
}
J1[6] = 1; // MUX WR line high
J1[5] = 1; // MUX CS line high
J1[7] = 0; // MUX EN line drop
}
for (volatile int i = 0; i < 32; i++)
{
iprintf("Channel: 0x%X", MYSYS_MUX[i]);
if (MUX_OUT[i] == MYSYS_FAULT_FOUND) iprintf(" Fault.\r\n");
else iprintf(" No Fualt.\r\n");
OSTimeDly(TICKS_PER_SECOND/20);
}
}
}
-
- Posts: 513
- Joined: Sat Apr 26, 2008 7:14 am
Re: MOD54415 HiRes Timer vs Watchdog
Jedi: I have not gone thru your code in detail, but a cursory inspection suggests that the MUX code polls 32 positions, and for each, starts and then waits for the DSPI to complete. It also calls some iprintf() functions. IMO this is WAY to much to be happening inside an ISR, even at the low rates you mention. Again, IMO, this would be much better implemented in a task triggered by a semaphore posted by the timer ISR. As I mentioned earlier, the PIT timer example already will post that periodic semaphore. All you need to do is create a task something like:
void FunctionForMyMuxTask (void *pd) {
while (1) {
OSSemPend( &MyTimerISRSemaphore, 0);
MuxRead();
}
}
Then you create the Semaphore: OS_SEM MyISRTimerSemaphore ;
Init the semaphore: OSSemInit( &MyISRTimerSemaphore, 0);
create the MuxTask using something like: OSSimpleTaskCreate( &FunctionForMyMuxTask , MAIN_PRIO + 1);
Look at the NB Semaphore demo at: C:\nburn\examples\StandardStack\RTOS\OSSemaphore
I've also attached a few add'l semaphore project examples that build on the NB example.
Maybe these will be helpful in familiarizing you w/ tasks?
void FunctionForMyMuxTask (void *pd) {
while (1) {
OSSemPend( &MyTimerISRSemaphore, 0);
MuxRead();
}
}
Then you create the Semaphore: OS_SEM MyISRTimerSemaphore ;
Init the semaphore: OSSemInit( &MyISRTimerSemaphore, 0);
create the MuxTask using something like: OSSimpleTaskCreate( &FunctionForMyMuxTask , MAIN_PRIO + 1);
Look at the NB Semaphore demo at: C:\nburn\examples\StandardStack\RTOS\OSSemaphore
I've also attached a few add'l semaphore project examples that build on the NB example.
Maybe these will be helpful in familiarizing you w/ tasks?
- Attachments
-
- SemaphoreExamples.zip
- (1.62 MiB) Downloaded 578 times
Re: MOD54415 HiRes Timer vs Watchdog
Yea... you really can't call drivers in an IRQ. It turns out, a lot of them rely on interrupts triggering to work. You really want to have the timer post to a semaphore that a task is waiting on and then have the task perform the actual... task.
-Dan
-Dan
Dan Ciliske
Project Engineer
Netburner, Inc
Project Engineer
Netburner, Inc
-
- Posts: 192
- Joined: Mon Dec 17, 2012 6:24 am
Re: MOD54415 HiRes Timer vs Watchdog
Thanks Dan, so I'm assuming that RidgeGlider was correct then in recommending the PIT. Unless the HiRes Timer works with semaphores... Can't call drivers in IRQ - I would assume this applies to the external Pin IRQs as well?
RidgeGlider - I'm going to give it a go with the HiRes timer and a semaphore first, then try the PIT. I'll update when I get it going. I may also post a few questions if I get stuck but I'll do my best not to.
RidgeGlider - I'm going to give it a go with the HiRes timer and a semaphore first, then try the PIT. I'll update when I get it going. I may also post a few questions if I get stuck but I'll do my best not to.
-
- Posts: 513
- Joined: Sat Apr 26, 2008 7:14 am
Re: MOD54415 HiRes Timer vs Watchdog
Jedi: Bottom line, both the PIT and the DMA timer (aka the HiRes when used w/ the NB interface) are hardware driven timing modules. Both can operate in polled mode, or w/ISRs, and sometimes, importantly by manipulating specific IO lines completely w/o any processor overhead (eg no ISRs!) after they're configured and turned on. To use the HiRes w/ a semaphore just define a function that posts the semaphore, and point the timer to run upon completion using setInterruptFunction(). You will need a task that pends on the semaphore. Either timer will work, the PIT just costs less and is simpler I think. Of course, it would not hurt to read up on the PIT or DMA modules in the Freescale manual!