2
\$\begingroup\$

There is a variable declaration:

uint16_t status = (*(__IO uint16_t*)PAGE0_BASE_ADDRESS);

__IO is the precompiler directive that becomes the keyword volatile. PAGE0_BASE_ADDRESS is the hex address, say 0x08000000;

I can't get my head around what this statement actually does. Anyone help please?

| improve this question | | | | |
\$\endgroup\$
  • \$\begingroup\$ This question has been asked many times over on stackoverflow.com. \$\endgroup\$ – Lundin Sep 11 '19 at 7:31
4
\$\begingroup\$

PAGE0_BASE_ADDRESS is an integer value; the subexpression (__IO uint16_t*)PAGE0_BASE_ADDRESS) expands to (volatile uint16_t*)PAGE0_BASE_ADDRESS), which casts the integer to a volatile pointer to 16-bit unsigned integer.

Finally, the outermost asterisk is used to deference this pointer. Overall, the statement reads a 16-bit integer from the given address, considering it as a pointer to volatile memory1, meaning that it must be read/written from memory each time it is accessed (i.e. the compiler should not cache it in a register or assume that its value remains the same each time the given code is executed).

1 Not the same as a volatile pointer to normal memory (i.e. uint16_t * volatile)

| improve this answer | | | | |
\$\endgroup\$
  • \$\begingroup\$ i didn't quite get what's the use of first casting int to a volatile pointer and then dereferencing it. could you please explain? \$\endgroup\$ – Dima Dz Sep 11 '19 at 6:55
  • \$\begingroup\$ @DimaDz The de-referencing is simply there to allow you to access the contents of the register. Apparently it is a 16 bit register, hence the uint16_t. \$\endgroup\$ – Lundin Sep 11 '19 at 7:33
  • \$\begingroup\$ @DimaDz The integer in question is the address, expressed as an integer. C/C++ doesn't allow you to directly dereference it as if it were a pointer (i.e. *someInt) is no good, since the type/size of data that ought to be read is unclear. Instead, the integer must first be cast to a pointer to volatile uint16_t, so the compiler knows to generate code that reads a uint16_t from the given location, without assuming that the value remains the same between reads (volatility) \$\endgroup\$ – nanofarad Sep 11 '19 at 14:54
2
\$\begingroup\$

Take the number 0x08000000, type-cast it as a pointer to a volatile uint16_t, then dereference that pointer to read the value at the address 0x08000000 in memory and put the result in the status variable.

volatile tells your compiler that the value stored at this address may change "unexpectedly" and that it can't just read he value once and store it in a register and use that stored value in future - it must re-read the value form the address in memory every time it's used.

This type of code is typical in microcontrollers when referring to peripheral registers - particularly status registers and data receive registers where the values contained in those registers depend on external events which are not known or predictable to/by the compiler.

| improve this answer | | | | |
\$\endgroup\$
1
\$\begingroup\$

It casts the address to a pointer which points to a 16-bit word. It then refers to it by reading the 16-bit word (from the address where the pointer points). The value is stored in the variable.

| improve this answer | | | | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.