OpenPIC timer usage?
gedare at rtems.org
Wed Aug 13 14:31:33 UTC 2014
I'm not a powerpc expert, but I have some questions for you to
consider. How long does it take the openpic_settimer() to take effect?
If the isr was delayed, could another timer interrupt fire before
setting the inhibit bit? Will both interrupts be received? This is
hw-dependent, and I don't know the answer for powerpc. Perhaps the
powerpc ISR_Handler clears the interrupt source before calling the
isr, so there might be time for another timer to fire? Or perhaps the
hardware buffers multiple interrupts received from the same source. If
so, then you would need to acknowledge the interrupt after clearing
the inhibit bit, so another interrupt that was queued from the same
source doesn't fire.
On Wed, Aug 13, 2014 at 3:58 AM, Nick Withers <nick.withers at anu.edu.au> wrote:
> Sorry, hit "Send" a bit quick...
> On Wed, 2014-08-13 at 16:42 +1000, Nick Withers wrote:
>> On Tue, 2014-08-12 at 12:48 +1000, Nick Withers wrote:
>> > Hullo all,
>> > Has anyone used an OpenPIC timer (see
>> > "c/src/lib/libbsp/powerpc/shared/openpic/") in single-shot mode before?
>> > I seem to be having some trouble with them, in particular ensuring that
>> > an ISR fires only once.
>> > According to "c/src/lib/libbsp/powerpc/mvme3100/README", "The setup
>> > routine allows for specifying single-shot or periodic mode", but I can't
>> > seem to see how to achieve the former.
>> > Going off
>> > "c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/nested_irq_test.c" I
>> > should at least openpic_maptimer(..., 0) and openpic_inittimer(..., ...,
>> > 0) to stop the timer. I've tried that in the ISR and the
>> > openpic_inittimer() call can stall indefinitely in
>> > openpic_safe_writefield() on "while (openpic_read(addr=0xe1041120) &
>> > OPENPIC_ACTIVITY);".
>> Turns out the "OpenPIC" on at least the MVME3100 is actually an IBM
>> MPIC, which has documentation! Huzzah!
>> So, to follow up, neigher openpic_inittimer() and openpic_maptimer()
>> need to be called to halt the timer and prevent further interrupts (but
>> need to be done to set the timer up before first use).
>> An openpic_settimer(..., OPENPIC_TIMER_COUNT_INHIBIT, 0) will do it.
>> Also note that for the hardware to latch a new time programmed through
>> openpic_settimer(), the OPENPIC_TIMER_COUNT_INHIBIT bit has to
>> transition from a 1 to a 0.
> So I think I'm driving the timer correctly (but if anyone else's ever
> used 'em, a double-check'd be loverly :-P).
> Any yet, it seems I'm potentially getting a double-ISR-hit, though I
> haven't been able to trigger it reliably; it feels like some kind of fun
> race condition.
> I've attached a minimised code sample (build with, e.g., "[g]make
> RTEMS_ROOT=/home/nick/rtems/rtems-4.11 BSP=mvme3100") which has been
> tested successfully (i.e., it shows the failure) through PSim and on
> MVME3100 hardware (though it's timing-dependent, so YMMV!). When
> mvme3100_timer_set()'s called, it:
> - Asserts that a semaphore's locked*
> - Asserts that the timer's currently stopped
> - printk()s 's'
> - Starts the timer
> - printk()s 'S'
> - Blocks on the semaphore
> - Asserts that the semaphore's locked
> - printk()s '_'
> - returns
> The timer's vectored to mvme3100_timer_interrupt() and when this is
> called, it:
> - Stops the timer (notionally, anyway! I've stepped through it in GDB
> and it seems to work as expected), through openpic_settimer(...,
> OPENPIC_TIMER_COUNT_INHIBIT, 0)
> - printk()s 'p'
> - Increments the semaphore
> - printk()s 'P'
> So I'm expecting, for each '_'-delimited block of text, to see one set
> of "s(...)S" for each "p(...)P".
> Here's part of a run in PSim:
> psim-cmds:5: Error in sourced command file:
> No symbol "the_source" in current context.
> (gdb) run
> Starting program: /usr/home/nick/projects/sem_isr/sem_isr.debug
> warning: failed to reevaluate condition for breakpoint 1: No symbol "the_source" in current context.
> OpenPIC Version 1.2 (2 CPUs and 17 IRQ sources) at 0x0C130000
> OpenPIC Vendor 0 (Unknown), Device 0 (Unknown), Stepping 0
> Overriding NumSources (17) from configuration with 16
> OpenPIC timer frequency is 1 Hz
> sSpP_sSpP_sSpP_sSpP_sSpP_sSpP_sSpP_sSpP_sSpPpP_assertion "rtems_semaphore_count(timer->semaphore) == 0" failed: file "mvme3100_timer.c", line 207, function: mvme3100_timer_wait
> [The reported OpenPIC timer frequency's not valid and certainly not
> being honoured in terms of actual timings - this is expected with PSim,
> isn't it?]
> That's consistent with what I see when running it on MVME3100 hardware
> (albeit typically with different interleavings of the ISR / task),
> except that there's no obvious double-up (e.g., the "pPpP" just before
> the assertion failure, above) - I presume because printk()'s output
> isn't guaranteed to make it out to a serial console before the assertion
> crashes it...?
> I guess it'd be nice for me to provide code that perhaps generates
> interrupts in another manner. Would anyone have any suggestions here? is
> there an rtems_interrupt_cause()-like that's implemented? Even if there
> is it might be hard to get the timings right without a higher-precision
>> > Any ideas? Perhaps I'm going about this the wrong way to begin with...
>> > What I'm after is a microsecond-precision-ish one-shot timer that'll be
>> > used thousands of times per second.
>> > Ta all!
> * Possibly dodgily: I implemented an rtems_semaphore_count kludge, but
> can't claim to actually understand what I did properly. I have observed
> the same symptoms using a POSIX semaphore (which to my knowledge isn't
> explicitly specified as being allowed in an RTEMS ISR, though ISTR
> seeing it somewhere before)
> Nick Withers
> Embedded Systems Programmer
> Department of Nuclear Physics, Research School of Physics and Engineering
> The Australian National University (CRICOS: 00120C)
> users mailing list
> users at rtems.org
More information about the users