[En-Nut-Discussion] FRC: Direct or Pointer

Harald Kipp harald.kipp at egnite.de
Mon Oct 31 11:19:36 CET 2011


Hi Ulrich,

On 30.10.2011 20:19, Ulrich Prinz wrote:
> Here is the new headline.

Good idea. Unfortunately all attribution lines are gone.
http://en.wikipedia.org/wiki/Posting_style#Attribution_lines

>>> Now what? As far as I know, Linux doesn't use structure pointers to
>>> access registers.
>>
>> Yeah, it doesn't for all platforms I've seen (AVR32 and Samsung ARMs).
>> It does more or less what we do, but they do exploit inline functions
>> a lot more than we do, and it makes the code better (more type safe
>> than macros)

In a local branch I'm already using the following new set of functions.

================== SNIP =====================

#if !defined (__ASSEMBLER__)
#define mem_barrier() __asm__ __volatile__("":::"memory")

static inline void mem_wr(unsigned int reg, unsigned int val)
{
    *(volatile unsigned int *) reg = val;
}

static inline void mem_wr8(unsigned int reg, uint8_t val)
{
    *(volatile uint8_t *) reg = val;
}

static inline void mem_wr16(unsigned int reg, uint16_t val)
{
    *(volatile uint16_t *) reg = val;
}

static inline void mem_wr32(unsigned int reg, uint32_t val)
{
    *(volatile uint32_t *) reg = val;
}

static inline unsigned int mem_rd(unsigned int reg)
{
    return *(const volatile unsigned int *) reg;
}

static inline uint8_t mem_rd8(unsigned int reg)
{
    return *(const volatile uint8_t *) reg;
}

static inline uint16_t mem_rd16(unsigned int reg)
{
    return *(const volatile uint16_t *) reg;
}

static inline uint32_t mem_rd32(unsigned int reg)
{
    return *(const volatile uint32_t *) reg;
}

static inline void mem_wr_mb(unsigned int reg, unsigned int val)
{
    mem_wr(reg, val);
    mem_barrier();
}

static inline void mem_wr8_mb(unsigned int reg, uint8_t val)
{
    mem_wr8(reg, val);
    mem_barrier();
}

static inline void mem_wr16_mb(unsigned int reg, uint16_t val)
{
    mem_wr16(reg, val);
    mem_barrier();
}

static inline void mem_wr32_mb(unsigned int reg, uint32_t val)
{
    mem_wr32(reg, val);
    mem_barrier();
}

static inline unsigned int mem_rd_mb(unsigned int reg)
{
    unsigned int rc = mem_rd(reg);
    mem_barrier();

    return rc;
}

static inline uint8_t mem_rd8_mb(unsigned int reg)
{
    uint8_t rc = mem_rd8(reg);
    mem_barrier();

    return rc;
}

static inline uint16_t mem_rd16_mb(unsigned int reg)
{
    uint16_t rc = mem_rd16(reg);
    mem_barrier();

    return rc;
}

static inline uint32_t mem_rd32_mb(unsigned int reg)
{
    uint32_t rc = mem_rd32(reg);
    mem_barrier();

    return rc;
}

#endif /* __ASSEMBLER__ */

================== SNAP =====================

Comments are welcome.

There are two reasons for not committing them until now. One problem with static inline is the incompatibility among compilers.

http://www.greenend.org.uk/rjk/2003/03/inline.html
seems to provide an acceptable solution.

The other reason was the directory structure, which had been discussed in the parent thread.

One problem with structures is, that they are entirely based on volatiles. Compilers are more or less all broken here and it will never get fixed, IMHO.

OK, I can hear you shouting: "But you are using volatiles as well!" Right, _but_ the inline function offers all options, they are most flexible. I _can_ use volatiles, but I _must_ not. Access via structures is convenient for the programmer only. They are difficult to adept to different requirements.

Regards,

Harald



More information about the En-Nut-Discussion mailing list