Skip to main content
Lars Beiderbecke
Senior III
May 26, 2020
Solved

"Supertype" of uint8_t * and __IO uint8_t *?

  • May 26, 2020
  • 10 replies
  • 3696 views

This questions is mildly naive, but is there a way to define a function f() so that one parameter p accepts both uint8_t * and __IO uint8_t * arguments, i.e., function f() writes either to internal SRAM or external SDRAM depending on the pointer passed?

For example, what would I need to write instead of _______?

void memset(_____ *p, char x, unsigned count)
{
 while (count--)
 *p++ = x;
}
 
__IO uint8_t *q = ...;
memset(q, 'a', 10);
 
uint8_t *r = ...;
memset(r, 'b', 10);

It would be quite wasteful if I had to implement the same function twice, once for each memory type.

    This topic has been closed for replies.
    Best answer by TDK

    > If so, why is access to regular SRAM not volatile?

    The reasons for using volatile will depend on your program usage of the memory and not the memory itself. If you're only accessing memory within a main loop, and interrupts don't touch it, there is no need to use volatile, regardless of the memory type. If memory can be changed within interrupts, and you want the main loop to re-read that register on every access, you need to use volatile to prevent the compiler from optimizing it away.

    > I also still don't know why ST introduced that __IO thing (besides adding volatile)? The definition mentions "read/write permissions", but no one is checking this?!

    There's nothing to enforce with __IO. You can't do anything except read or write to the register.

    Registers defined as __I are enforced to be read-only using const. Not sure offhand why it's different in C++ than in C here.

    Registers defined as __O can't be enforced to be write-only since there's no such restriction in C.

    #ifdef __cplusplus
     #define __I volatile /*!< Defines 'read only' permissions */
    #else
     #define __I volatile const /*!< Defines 'read only' permissions */
    #endif
    #define __O volatile /*!< Defines 'write only' permissions */
    #define __IO volatile /*!< Defines 'read / write' permissions */

    10 replies

    Lars Beiderbecke
    Senior III
    May 26, 2020

    (Talking to myself again.)

    What exactly does __IO do anyway, besides adding volatile? Writing to SRAM and SDRAM just differs by address (0x20000000 vs 0xC000 0000) ...

    Uwe Bonnes
    Chief
    May 26, 2020

    _IO marks a register access as volatile

    Lars Beiderbecke
    Senior III
    May 26, 2020

    I confirmed by experiment that __IO is not required to write to SDRAM. So the original questions is answered by using volatile uint8_t.

    But if we assume that only the STM32 accesses the SDRAM, can we also drop volatile?

    TDK
    May 26, 2020

    You can define the argument as a void * and cast it to uint8_t * within the function itself. Any pointer can be converted to void * implicitly.

    Nevermind, doesn't work.

    "If you feel a post has answered your question, please click ""Accept as Solution""."
    turboscrew
    Senior III
    May 26, 2020

    Why not write to RAM too as volatile? Does it take too much toll in optimizations?

    Lars Beiderbecke
    Senior III
    May 26, 2020

    No, in fact I'll probably do that, although dropping volatile seems to work, too.

    Pavel A.
    Super User
    May 26, 2020

    In C++ volatile and normal parameters are differentiated.

    So if C++ is your preferred language (and the way of thinking) this question is not naive.

    If a function parameter is declared volatile, it will not try to optimize (reorder, coalesce) writes in any way.

    Non-volatile implementation can optimize.

    Security folks know that a simple memset(buffer,0, sizeof(buffer) may let the buffer not zeroed,

    so they invented "secure_memset" variants that work for sure.

    -- pa

    Lars Beiderbecke
    Senior III
    May 26, 2020

    Based on your remark, I found a remark on the net that memset() might be optimized away, which volatile would prevent. Is that the reason for its use here? (For a non-RTOS application, which has exclusive control over SDRAM, memory contents wouldn't change randomly.) If so, why is access to regular SRAM not volatile?

    I also still don't know why ST introduced that __IO thing (besides adding volatile)? The definition mentions "read/write permissions", but no one is checking this?!

    Pavel A.
    Super User
    May 26, 2020

    > I also still don't know why ST introduced that __IO thing (besides adding volatile)?

    Oh... This question can break loose quite a can of worms.

    My short answer is, it depends on the MCU family. M0 are simple.

    M7 have advanced data cache control options that can be set thru the MPU.

    Declaring things volatile is the simplest move to a "working" code, even if it is not most optimized or academically correct.

    Volatile has also other useful effect of serving a memory barrier to prevent reordering by the compiler.

    But this is another can of worms.

    Enjoy the ARM architecture...

    -- pa

    TDK
    TDKBest answer
    May 26, 2020

    > If so, why is access to regular SRAM not volatile?

    The reasons for using volatile will depend on your program usage of the memory and not the memory itself. If you're only accessing memory within a main loop, and interrupts don't touch it, there is no need to use volatile, regardless of the memory type. If memory can be changed within interrupts, and you want the main loop to re-read that register on every access, you need to use volatile to prevent the compiler from optimizing it away.

    > I also still don't know why ST introduced that __IO thing (besides adding volatile)? The definition mentions "read/write permissions", but no one is checking this?!

    There's nothing to enforce with __IO. You can't do anything except read or write to the register.

    Registers defined as __I are enforced to be read-only using const. Not sure offhand why it's different in C++ than in C here.

    Registers defined as __O can't be enforced to be write-only since there's no such restriction in C.

    #ifdef __cplusplus
     #define __I volatile /*!< Defines 'read only' permissions */
    #else
     #define __I volatile const /*!< Defines 'read only' permissions */
    #endif
    #define __O volatile /*!< Defines 'write only' permissions */
    #define __IO volatile /*!< Defines 'read / write' permissions */

    "If you feel a post has answered your question, please click ""Accept as Solution""."
    Lars Beiderbecke
    Senior III
    May 26, 2020

    To summarize, I put way too much meaning over __IO, and the use of volatile should be based on actual use, although it is probably safer to do so. Thanks to all who replied. :clapping_hands:

    TDK
    May 26, 2020

    Yes, just be aware that most registers (in contrast to RAM) need volatile because they do not in general perform the same way as RAM. For example, you would not expect this to be true:

    CRC->DR = 0x67;
    assert(CRC->DR == 0x67);

    Same for SPI->DR or whatever you happen to be using. But the standard headers take care of that for you, as you saw.

    "If you feel a post has answered your question, please click ""Accept as Solution""."
    Piranha
    Principal III
    May 30, 2020

    @Pavel A.​ and everyone,

    > Volatile has also other useful effect of serving a memory barrier to prevent reordering by the compiler.

    Volatile is not a memory barrier. It prevents reordering only of volatile accesses relative to other volatile accesses, but doesn't prevent reordering of non-volatile accesses in any way.

    > My short answer is, it depends on the MCU family. M0 are simple.

    > M7 have advanced data cache control options that can be set thru the MPU.

    > Enjoy the ARM architecture...

    Volatile has nothing to do with M0, M7, ARM, MIPS, x86, AVR, PIC or any other specific hardware. It's a purely language/compiler feature.

    Guys, don't be like ST's code monkeys and take your time to understand and learn how to use this very important language/compiler feature!

    https://blog.regehr.org/archives/28

    http://softwareramblings.com/2008/05/demystifying-the-volatile-keyword.html

    https://community.st.com/s/question/0D50X0000C4Nk4GSQS/bug-missing-compiler-and-cpu-memory-barriers