This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Minor TivaWare header bug

Just realised this as I was looking at the declarations for DID0 and DID1 that they are wrong. Currently they are

#define SYSCTL_DID0_R           (*((volatile uint32_t *)0x400FE000))
#define SYSCTL_DID1_R           (*((volatile uint32_t *)0x400FE004))

They should be

#define SYSCTL_DID0_R           (*((const uint32_t *)0x400FE000))
#define SYSCTL_DID1_R           (*((const uint32_t *)0x400FE004))

They are not volatile, it does not matter if reads are skipped and they are not writeable. The missing const if probably the more severe bug, an unnecessary volatile just restricts the possible optimization the compiler can do. A missing const allows a write or RMW sequence error to be undetected.

I expect there are more of these in the code.

Robert

I think better still would be to declare them as proper variables rather than using defines but that's another thing entirely.

  • Hello Robert

    Thanks for bringing this up. The DRM examples are being converted to TivaWare and may in fact be deprecated in future releases (not the current one planned for release)

    Regards
    Amit
  • Robert Adsett said:
    I expect there are more of these in the code.

    And in fact to add to the list

    #define SYSCTL_RIS_R            (*((volatile uint32_t *)0x400FE050))

    should be

    #define SYSCTL_RIS_R            (*((const volatile uint32_t *)0x400FE050))

    since it is also read-only, but in this case each read must take place since the values can change.

    Robert

  • Hello Robert

    But a volatile would do the part of reading the register!

    Regards
    Amit
  • I think the register definitions are still going to be needed. One of TivaWare's strengths is that it does not force all access through a narrow chokehold for cases that it does not apply to. Either for performance reasons (which has not been a concern for me) or because TI did not have sufficient prescience to see the need for certain functionality.

    Also, presumably TivaWare itself uses these definitions. As such it makes sense for you to avail yourself of the error catching (and optimization) properties of proper definitions.

    Robert
  • Amit, That's why const volatile rather than const.

    Robert
  • Hello Robert

    TivaWare does not use the DRM macro's but the direct define of the register along with HWREG

    Regards
    Amit
  • Hello Robert

    Robert Adsett said:
    That's why const volatile rather than const.

    But you have suggested volatile to be changed as const volatile. I am now confused

    Regards

    Amit

  • Amit const is necessary because the register is read-only. Writes are not allowed. And volatile is necessary because all reads must be performed. Thus the declaration needs to be const volatile. Obviously const alone is an error, equally obviously volatile alone is an error,

    Robert
  • Amit, that's both ugly and error prone.

    Robert

    And a minor optimization hit.
  • Hello Robert

    A volatile would indicate both RW while const volatile would mean RO and that will allow the compiler to optimize!

    Regards
    Amit
  • Amit Ashara said:
    A volatile would indicate both RW while const volatile would mean RO and that will allow the compiler to optimize!

    No! absolutely not.

    const means no writes are allowed

    volatile means all reads and writes performed must be performed and in the order specified in the code (order can get a little fuzzy so you have to be careful in the writing, a good static analyzer helps here)

    volatile says nothing about whether reads or writes are allowed, const say nothing about whether all reads must be performed.

    The two can be combined and in good embedded code they often are.

    As an experiment try declaring a variable as const volatile. The compiler should declare an error if you try to write to it.

    Robert

    Unfortunately C/C++ have no keyword to indicate something is not readable so there is no syntax for a write-only register whose every write must be performed.

  • By way of reference

    (#3) Read-Only Hardware Register

    Sometimes you will run across a read-only hardware register. In addition to enforcing compile-time checking so that the software doesn’t try to overwrite the memory location, you also need to be sure that each and every requested read actually occurs. By declaring your variable IS A (constant) pointer TO A constant and volatile memory location you request all of the appropriate protections, as in:

    uint8_t const volatile * const p_latch_reg = (uint8_t *) 0x10000000;

    As you can see, the declarations of variables that involve both the volatile and const decorators can quickly become complicated to read. But the technique of combining C’s volatile and const keywords can be useful and even important. This is definitely something you should learn to master to be a master embedded software engineer.

    From Jack Barr in http://embeddedgurus.com/barr-code/category/coding-standards/

    More directly http://embeddedgurus.com/barr-code/2012/01/combining-cs-volatile-and-const-keywords/

    I've found him to be a pretty decent author

    Robert

  • Qualifier

    Example Register

    Caching allowed

    Writes Allowed

    Used for

    const

    SYSCTL_DID0_R

    Y

    N

    Read only registers that do not change

    volatile

    SYSCTL_MISC_R

    N

    Y

    Registers that may be read and written and for which each read or write must take place. For instance if a sequence of writes of different values cannot be replaced with the last value written or if each read could potentially return a different value, or if the read or write as a side effect in addition to the actual value. Note that write only registers also usually fit in this category

    const volatile

    SYSCTL_RIS_R

    N

    N

    Read only registers that change during operation or that have a side effect as a result of the read.

    Unqualified

     

    Y

    Y

    Registers for which only the final value matters when written and for which the value read can be read at any time. There must be no side effects to the read and write. The effects of a write can wait until a point in the program where the results must be written to a global such as a function call or return. This requirement can seldom be reliably and predictably met.

    Summarising

  • Hello Robert,

    Thank you for the table. But I am afraid that any change would not be soon.

    Regards
    Amit
  • I'm not expecting a change Amit. I do consider it a minor bug. It just seemed a convenient amplification.

    Robert