2020-05-26 3:33 AM
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.
Solved! Go to Solution.
2020-05-26 6:14 AM
> 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 */
2020-05-26 3:53 AM
(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) ...
2020-05-26 4:29 AM
_IO marks a register access as volatile
2020-05-26 4:54 AM
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?
2020-05-26 5:35 AM
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.
2020-05-26 5:48 AM
Why not write to RAM too as volatile? Does it take too much toll in optimizations?
2020-05-26 5:49 AM
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
2020-05-26 6:07 AM
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?!
2020-05-26 6:09 AM
No, in fact I'll probably do that, although dropping volatile seems to work, too.
2020-05-26 6:14 AM
> 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 */