epics-modules/devlib2

Macrized ioread causes multiple accesses

mdavidsaver opened this issue · 3 comments

Andrew Johnson and Shifu Xu of ANL report a nasty bug with epicsMMIO.h effecting all targets except RTEMS/powerpc. This is known to cause incorrect behavior with mrfioc2 on vxWorks, though this particular issue won't manifest on other targets.

On 07/01/2016 05:51 PM, Andrew Johnson wrote:

...
Register reads from the MRF230 are done by calling READ32.

In mrfCommonIO.h:

define READ32(base,offset) NAT_READ32(base,offset)

define NAT_READ32(base,offset) \

    nat_ioread32 ((epicsUInt8 *)(base) + U32_ ## offset)

In epicsMMIO.h:

define nat_ioread32(address) bswap32(sysPciInLong((UINT32 *)(address)))

For a PowerPC:

define bswap32(value) ( \

(((epicsUInt32)(value) & 0x000000ff) << 24) |
(((epicsUInt32)(value) & 0x0000ff00) << 8) |
(((epicsUInt32)(value) & 0x00ff0000) >> 8) |
(((epicsUInt32)(value) & 0xff000000) >> 24))

Expanding out the bswap32() macro in nat_ioread32 results in

define nat_ioread32(address) ( \

(((epicsUInt32)(sysPciInLong((UINT32 *)(address))) & 0x000000ff) <<
24) |
(((epicsUInt32)(sysPciInLong((UINT32 *)(address))) & 0x0000ff00) << 8) |
(((epicsUInt32)(sysPciInLong((UINT32 *)(address))) & 0x00ff0000) >> 8) |
(((epicsUInt32)(sysPciInLong((UINT32 *)(address))) & 0xff000000) >> 24))

i.e. four actual reads for every call to READ32. If the register is a
FIFO, that's probably going to throw away entries.
...

Candidate fix a13a345

@anjohnson fyi

This fix resolves our problem with the MRF EVR-230 board on VxWorks.