cancel
Showing results for 
Search instead for 
Did you mean: 

"Supertype" of uint8_t * and __IO uint8_t *?

Lars Beiderbecke
Senior III

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 discussion is locked. Please start a new topic to ask your question.
1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Super User

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

View solution in original post

13 REPLIES 13
Lars Beiderbecke
Senior III

(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
Principal III

_IO marks a register access as volatile

Lars Beiderbecke
Senior III

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
Super User

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

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

Pavel A.
Super User

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

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?!

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

TDK
Super User

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