VME board problem

Till Straumann strauman at slac.stanford.edu
Fri Jan 19 08:23:51 UTC 2007

A quick look at your

void done(int addr)
    unsigned char x;

    do {
        x = *(unsigned char *)(addr+CR10);
    } while(x & 0x8);

routine reveals a typical, excuse me, novice error.
Device register pointers must be declared 'volatile'
[here: (volatile unsigned char*)].
Otherwise, the compiler (RTEMS' gcc is probably more
recent than vxworks' and hence optimizes more aggressively)
optimizes your code into

if ( (*(unsigned char*)(addr + CR10)) & 0x8 )
    while (1);

(because it doesn't know that the register contents
can change due to 'external' causes).

IMHO this way of accessing device registers is
generally bad practice:
  - device access is not explicit but implicit
  - not portable (endian issues in case of wider registers,
    execution ordering issues)

In particular, be aware that the powerpc (and other
modern CPUs probably, too) don't necessarily execute
instructions in the order you code them. The powerpc
may reorder instructions if this wouldn't change program
behavior under the assumption that all accesses are
to 'ordinary memory' w/o side effects.

Consider, e.g., a device with two registers: a 'trigger'
register and a 'result' register. Writing something to 'trigger'
causes the device to do something and the result of the operation
can be read from the 'result' register.

read_device() {
 *trigger_reg_p = 1;
 return *result_reg_p;

Even if the compiler generated instructions exactly in the
specified order, the powerpc may still execute them as

 x = *result_reg_p;
 *trigger_reg_p = 1;
 return x;

(because if '*result_reg_p' and '*trigger_reg_p' were ordinary
variables in memory this reordering wouldn't matter but may
allow for more efficient use of CPU resources.)

A special instruction ('eieio') is required to enforce ordering of
the load with respect to the store operation.

For these reasons, it is strongly recommended to use the
I/O operations defined in libcpu/io.h

-- Till

Artem Kazakov wrote:
> Hello everybody.
> I'm using RTEMS-4.6.99 on MVME-5500 board.
> Recently I tried to use an ADC board PVME-303 and I failed. I have a
> simple test program which successfully runs under VxWorks, but under
> RTEMS it just loops forever.
> In short the program does the following: it makes several writes to
> configuration registers of ADC board. And then it reads DATA register
> for data.
> After configuring the ADC board and before reading data, the program
> is supposed to check "DONE" bit. When it turns 0 we can proceed to
> reading data. But for some unknown reason "DONE" bit never turns 0
> when I use RTEMS.
> The only difference between those two programs is that under RTEM
> environment VME A24 window is locate on 0x9f000000 and under VxWorks
> it is located on 0xeff00000.
> And of course necessery headers are added in RTEMS case.
> Any suggestions what might be the cause of that behaviour?
> What to check?
> Please help me.
> I attach two versions of the program for VxWork and for RTEMS.
> Best regards,
> Artem Kazakov
> ------------------------------------------------------------------------
> _______________________________________________
> rtems-users mailing list
> rtems-users at rtems.com
> http://rtems.rtems.org/mailman/listinfo/rtems-users

More information about the users mailing list