OpenPIC timer usage?

Nick Withers nick.withers at anu.edu.au
Wed Aug 13 07:58:10 UTC 2014


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[1]! 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
Starting...
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
timer.

> > 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!
> 
> [1]
> https://www-01.ibm.com/chips/techlib/techlib.nsf/techdocs/F27971551C9EED8E8525774A0048770A/$file/mpic_db_05_16_2011.pdf

* 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)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: sem_isr.tar.gz
Type: application/x-compressed-tar
Size: 3998 bytes
Desc: not available
URL: <http://lists.rtems.org/pipermail/users/attachments/20140813/4822cb5d/attachment-0002.bin>


More information about the users mailing list