epics-modules / devlib2

Helper library for memory mapped bus access
http://epics-modules.github.io/devlib2/
Other
4 stars 8 forks source link

Macrized ioread causes multiple accesses #1

Closed mdavidsaver closed 8 years ago

mdavidsaver commented 8 years ago

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. ...

mdavidsaver commented 8 years ago

This is also https://bugs.launchpad.net/epics-base/+bug/1599903

mdavidsaver commented 8 years ago

Candidate fix a13a345ef18a095992538b576c5526c9a866e1a2

@anjohnson fyi

anjohnson commented 8 years ago

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